HDU 5294 Tricks Device 残余网络(最短路+最大流)**

来源:互联网 发布:淘宝如何搜索苍蝇水 编辑:程序博客网 时间:2024/06/05 01:48

题意:一个人抓另一个人,有一个地图(无向),纯洁的Wu抓到Zhang的条件是:只有走最短路才能抓到他。纯洁Wu在1点,Zhang在n点。

问你Zhang要最少切断几条路可以使纯洁Wu抓不到他,还有一个问题就是Zhang最多切了多少条边使得纯洁Wu还有机会抓到他。


做法:首先看第一个问题,要求的就是从点1到点n,有几条没有边重复的最短路(这里不是说找完了最短路把它删掉,再找最短路,这样的话所有的可以通向终点的都可以认为是最短路,而是长度同为首次找到的起点连接到终点的路径),再来看第二个问题,其实最多可以切的路段,即保留source到sink的最短路中路段最短的路径,其它的都可以切掉。

因为留下的这个路径满足纯洁Wu抓到Zhang的条件。


实施过程:首先我们可以通过单源最短路算法求出以点1为源点的所有最短路(dijstra,spfa...),此时新建一个原图满足dis[v]=dis[u]+w[u->v]的图,此时的图里面存的路径只要它可以走到终点,那么这条路径就是可以让纯洁Wu找到Zhang。

                          

如果就如上图所示Zhang最少要切掉2条,如果将其想象成网络流,当每一条边的容流量都是1的时候,显然有公共边的路径只能跑一次,这样在新图中运用最大流算法,求解即可。

注意:在求最短路的时候,定义一个路段数的数组L[p],即从源点走到p点,所经过的最小的路段数,一定要理解它的更新。

#include<iostream>#include<cstring>#include<cstdio>#include<queue>#define it __int64#define inf 0x7fffffffusing namespace std;const int N=2000+5;const int M=60000+5;int n,m;struct node{int v,next;int w;}e[M*2];struct nodee{int v,next;int flow;}ne[M*2];int head[N],cnt,nhead[N],ncnt,tiao;int s,t;void Init(){memset(head,-1,sizeof(head));memset(nhead,-1,sizeof(nhead));cnt=ncnt=0;}void add(int a,int b,int c){e[cnt].v=b;e[cnt].w=c;e[cnt].next=head[a];head[a]=cnt++;}void nadd(int a,int b,int c){ne[ncnt].v=b;ne[ncnt].flow=c;ne[ncnt].next=nhead[a];nhead[a]=ncnt++;ne[ncnt].v=a;ne[ncnt].flow=0;ne[ncnt].next=nhead[b];nhead[b]=ncnt++;} void Input(){for(int i=1;i<=m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a==b) continue;add(a,b,c);add(b,a,c);}s=1;t=n;}class Dinic{public:void spfa(){queue<int>q;while(!q.empty()) q.pop();for(int i=1;i<=n;i++){dis[i]=inf;vis[i]=0;l[i]=inf;}dis[s]=0;l[s]=0;vis[s]=1;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(dis[v]>dis[u]+e[i].w){dis[v]=dis[u]+e[i].w;l[v]=l[u]+1;if(!vis[v]){vis[v]=1;q.push(v);}}else if(dis[v]==dis[u]+e[i].w){if(l[v]>l[u]+1){    l[v]=l[u]+1;    if(!vis[v])    {    vis[v]=1;    q.push(v);    }}}}}tiao=l[t];}void build_map(){for(int i=1;i<=n;i++){for(int j=head[i];j+1;j=e[j].next){int v=e[j].v;if(dis[v]==dis[i]+e[j].w){nadd(i,v,1);}}}}int spath(){queue<int>q;while(!q.empty()) q.pop();memset(ndis,-1,sizeof(ndis));ndis[s]=0;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=nhead[u];i+1;i=ne[i].next){int v=ne[i].v;if(ndis[v]==-1&&ne[i].flow>0){ndis[v]=ndis[u]+1;    q.push(v);}}}return ndis[t]!=-1;}int Min(int a,int b){if(a<b) return a;return b;}int dfs(int u,int flow){int cost=0;if(u==t) return flow;for(int i=nhead[u];i+1;i=ne[i].next){int v=ne[i].v;if(ndis[v]==ndis[u]+1&&ne[i].flow>0){int min=dfs(v,Min(flow-cost,ne[i].flow));if(min>0){ne[i].flow-=min;ne[i^1].flow+=min;cost+=min;if(cost==flow) break;}else ndis[v]=-1;}}return cost;}int solve(){int res=0;while(spath()){res+=dfs(s,inf);}return res;}private:it dis[N];int vis[N],l[N],ndis[N];}dinic;void Output(){dinic.spfa();dinic.build_map();printf("%d %d\n",dinic.solve(),m-tiao);}int main(){while(~scanf("%d%d",&n,&m)){Init();Input();Output();}return 0;} 

0 0
原创粉丝点击