HDU 3599 War 求最短路+最大流
2011-07-15 23:02
495 查看
题目描述:在一个包含有N个点的无向图中求出从标号为1到N的边不相交的路径,点可以相交。
解题报告:先求一遍最短路,能满足从1到n是最短路的边一点满足d[j]==d[i]+w[i][j](d[i]为点1到点i的最短路,w[i][j]为i到j的边权) 把这样的i,j在流网络中建一条边权为1的有向边;最后以1为源,n为汇求一次最大流,这样就是无重边的最短路的数目了
解题报告:先求一遍最短路,能满足从1到n是最短路的边一点满足d[j]==d[i]+w[i][j](d[i]为点1到点i的最短路,w[i][j]为i到j的边权) 把这样的i,j在流网络中建一条边权为1的有向边;最后以1为源,n为汇求一次最大流,这样就是无重边的最短路的数目了
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<map> #define maxn 2000 #define inf 99999999 using namespace std; int d[1600],vis[maxn];//d[i] 到i的最短路途 int n,s,t; struct Node// 此题中有两种运用,第一:v表示终点,w表示边权;第二:表达到v的最短路为w; { int v,w; Node(int a,int b){ v=a;w=b;} bool friend operator <(Node x,Node y){ return x.w>y.w;}//重载< ,使得Node第二种表示下在优先队列内以w升序排列,优化dij }; vector<Node> node[maxn];//node[i] i点可达的点 //************************************************** //为dinic求最大流模版 struct edge { int v, next; int val; } net[ 100010 ]; int level[maxn], Qu[maxn], out[maxn],next[maxn]; class Dinic { public: int end; Dinic() { end = 0; memset( next, -1, sizeof(next) ); } inline void insert( int x, int y, int c) { net[end].v = y, net[end].val = c, net[end].next = next[x], next[x] = end ++; net[end].v = x, net[end].val = 0, net[end].next = next[y], next[y] = end ++; } bool BFS( int S, int E ) { memset( level, -1, sizeof(level) ); int low = 0, high = 1; Qu[0] = S, level[S] = 0; for( ; low < high; ) { int x = Qu[low]; for( int i = next[x]; i != -1; i = net[i].next ) { if( net[i].val == 0 ) continue; int y = net[i].v; if( level[y] == -1 ) { level[y] = level[x] + 1; Qu[ high ++] = y; } } low ++; } return level[E] != -1; } int MaxFlow( int S, int E ){ int maxflow = 0; for( ; BFS(S, E) ; ) { memcpy( out, next, sizeof(out) ); int now = -1; for( ;; ) { if( now < 0 ) { int cur = out[S]; for(; cur != -1 ; cur = net[cur].next ) if( net[cur].val && out[net[cur].v] != -1 && level[net[cur].v] == 1 ) break; if( cur >= 0 ) Qu[ ++now ] = cur, out[S] = net[cur].next; else break; } int u = net[ Qu[now] ].v; if( u == E ) { int flow = inf; int index = -1; for( int i = 0; i <= now; i ++ ) { if( flow > net[ Qu[i] ].val ) flow = net[ Qu[i] ].val, index = i; } maxflow += flow; for( int i = 0; i <= now; i ++ ) net[Qu[i]].val -= flow, net[Qu[i]^1].val += flow; for( int i = 0; i <= now; i ++ ) { if( net[ Qu[i] ].val == 0 ) { now = index - 1; break; } } } else{ int cur = out[u]; for(; cur != -1; cur = net[cur].next ) if (net[cur].val && out[net[cur].v] != -1 && level[u] + 1 == level[net[cur].v]) break; if( cur != -1 ) Qu[++ now] = cur, out[u] = net[cur].next; else out[u] = -1, now --; } } } return maxflow; } }; //*************************************************** int init() { int u,v,w; scanf("%d",&n); for(int i=0;i<=n;i++) { node[i].clear(); d[i]=inf; vis[i]=0; } s=1,t=n; while(scanf("%d%d%d",&u,&v,&w),u+v+w) { node[u].push_back(Node(v,w)); node[v].push_back(Node(u,w)); } if(n==1)return 1; else return 0; } int dij()//优先队列优化的dij { d[s]=0; priority_queue<Node> q; q.push(Node(s,d[s])); while(!q.empty()) { Node u=q.top();q.pop(); if(vis[u.v])continue; vis[u.v]=1; int size=node[u.v].size(); for(int j=0;j<size;j++) { Node k=node[u.v][j]; if(d[k.v]>d[u.v]+k.w) { d[k.v]=d[u.v]+k.w; q.push(Node(k.v,d[k.v])); } } } return d[t]; } // int EK()// 开始用EK写最大流,发现超时后套用了dinic模版 // { // queue<int> q; // memset(flow,0,sizeof(flow)); // int f=0; // for(;;) // { // memset(a,0,sizeof(a)); // a[s]=INF; // q.push(s); // while(!q.empty()) // { // int u=q.front();q.pop(); // for(int v=1;v<=n;v++) // if(!a[v]&&cap[u][v]>flow[u][v]) // { // fa[v]=u;q.push(v); // a[v]=min(a[u],cap[u][v]-flow[u][v]); // } // } // if(a[t]==0)break; // for(int u=t;u!=s;u=fa[u]) // { // flow[fa[u]][u]+=a[t]; // flow[u][fa[u]]-=a[t]; // } // f+=a[t]; // } // return f; // } void solve() { if(dij()==inf){printf("0\n");return ;}//如果不存在最短路,则为0条 Dinic my; for(int i=1;i<=n;i++) { int size=node[i].size(); for(int j=0;j<size;j++) { int v=node[i][j].v; if(d[v]==d[i]+node[i][j].w) { my.insert(i,v,1); //在流网络中建立i到j的一条边 } } } printf("%d\n",my.MaxFlow(s,t)); } int main() { int Case; scanf("%d",&Case); while(Case--) { if(init()) printf("0\n"); else solve(); } return 0; }
相关文章推荐
- hdu 3599 War(最短路+最大流)
- hdu 3599(最短路+最大流)
- HDU 3599 最短路+最大流
- hdu 3599(最短路+最大流)
- hdu 3416 Marriage Match IV (最短路+最大流)
- HDU 3416 Marriage Match IV(最短路+最大流)
- 多校 hdu 5294 Tricks Device 最短路+最大流
- HDU 5294 Tricks Device (最大流+最短路)
- HDU 1596 find the safest road 最短路求最大值
- HDU-3416 Marriage Match IV(最短路+最大流)
- hdu 5294 Tricks Device(最短路 + 最大流)
- HDU 5294 Tricks Device(最短路+最大流)
- HDU 3035 War 平面图最小割转化为最短路
- hdu 3416 最短路+最大流
- HDU 3035 War (对偶图转最短路)
- hdu 3416(最短路+最大流)
- HDU 5294 Tricks Device 最短路+最大流
- hdu 5137 去掉一个点 使得最短路最大(2014广州现场赛 K题)
- HDU 5889 Barricade (单源最短路 + 最小割(最大流))
- hdu 3416 Marriage Match IV 【 最短路 最大流 】