学会了网络流,就经常闲的没事儿刷网络流……于是乎来一发题解。
1. COGS2093 花园的守护之神
题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长。
用Dijkstra或者SPFA跑出来s-t最短路,然后把最短路DAG上的每条边的容量设为1,跑最小割即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define INF ((~((1)<<(31)))>>(1)) 6 using namespace std; 7 const int maxn=1010,maxe=500010; 8 struct edge1{int from,to,prev;long long dis;}e1[maxe<<1]; 9 struct edge2{int to,cap,prev;}e2[maxe<<1]; 10 struct node{ 11 int x; 12 long long dis; 13 node(int x,long long dis):x(x),dis(dis){} 14 bool operator<(const node &a)const{return dis>a.dis;} 15 }; 16 void addedge1(int,int,long long); 17 void addedge2(int,int,int); 18 void Dijkstra(int,long long*); 19 int Dinic(); 20 void bfs(); 21 int dfs(int,int); 22 int n,m,s,t,last1[maxn]={0},len1=0,last2[maxn],len2=0,now[maxn],d[maxn],q[maxn],head,tail,x,y; 23 long long dis[maxn],redis[maxn],z; 24 bool vis[maxn]; 25 int main(){ 26 #define MINE 27 #ifdef MINE 28 freopen("greendam2002.in","r",stdin); 29 freopen("greendam2002.out","w",stdout); 30 #endif 31 memset(last2,-1,sizeof(last2)); 32 scanf("%d%d%d%d",&n,&m,&s,&t); 33 for(int i=1;i<=m;i++){ 34 scanf("%d%d%lld",&x,&y,&z); 35 addedge1(x,y,z); 36 addedge1(y,x,z); 37 } 38 Dijkstra(s,dis); 39 Dijkstra(t,redis); 40 for(int i=1;i<=(m<<1);i++)if(dis[e1[i].from]+e1[i].dis+redis[e1[i].to]==dis[t]){ 41 addedge2(e1[i].from,e1[i].to,1); 42 addedge2(e1[i].to,e1[i].from,0); 43 } 44 printf("%d",Dinic()); 45 #ifndef MINE 46 printf("\n--------------------DONE--------------------\n"); 47 for(;;); 48 #endif 49 return 0; 50 } 51 void addedge1(int x,int y,long long z){ 52 e1[++len1].from=x; 53 e1[len1].to=y; 54 e1[len1].dis=z; 55 e1[len1].prev=last1[x]; 56 last1[x]=len1; 57 } 58 void addedge2(int x,int y,int z){ 59 e2[len2].to=y; 60 e2[len2].cap=z; 61 e2[len2].prev=last2[x]; 62 last2[x]=len2++; 63 } 64 void Dijkstra(int x,long long *dis){ 65 memset(vis,0,sizeof(vis)); 66 priority_queue<node>q; 67 memset(dis,63,sizeof(long long)*maxn); 68 dis[x]=0; 69 q.push(node(x,0)); 70 while(!q.empty()){ 71 x=q.top().x; 72 q.pop(); 73 if(vis[x])continue; 74 vis[x]=true; 75 for(int i=last1[x];i;i=e1[i].prev)if(dis[e1[i].to]>dis[x]+e1[i].dis){ 76 dis[e1[i].to]=dis[x]+e1[i].dis; 77 q.push(node(e1[i].to,dis[e1[i].to])); 78 } 79 } 80 } 81 int Dinic(){ 82 int ans=0; 83 for(;;){ 84 bfs(); 85 if(d[t]==INF)break; 86 memset(now,0,sizeof(now)); 87 ans+=dfs(s,INF); 88 } 89 return ans; 90 } 91 void bfs(){ 92 int x; 93 fill_n(d+1,n,INF); 94 d[s]=0; 95 head=tail=0; 96 q[tail++]=s; 97 while(head!=tail){ 98 x=q[head++]; 99 for(int i=last2[x];i!=-1;i=e2[i].prev)if(e2[i].cap>0&&d[e2[i].to]==INF){ 100 d[e2[i].to]=d[x]+1; 101 q[tail++]=e2[i].to; 102 } 103 } 104 } 105 int dfs(int x,int delta){ 106 if(x==t||!delta)return delta; 107 int flow=0,f; 108 for(int i=(now[x]?e2[now[x]].prev:last2[x]);i!=-1;i=e2[i].prev)if(e2[i].cap>0&&d[e2[i].to]==d[x]+1){ 109 now[x]=i; 110 f=dfs(e2[i].to,min(delta,e2[i].cap)); 111 if(!f)continue; 112 e2[i].cap-=f; 113 e2[i^1].cap+=f; 114 flow+=f; 115 delta-=f; 116 if(!delta)break; 117 } 118 return flow; 119 }