poj 3204 Ikki's Story I - Road Reconstruction(最大流,增广路)

来源:互联网 发布:灰鸽子软件下载 编辑:程序博客网 时间:2024/06/06 03:44

题目链接
Ikki's Story I - Road Reconstruction
Time Limit: 2000MS Memory Limit: 131072KTotal Submissions: 7576 Accepted: 2194

Description

Ikki is the king of a small country – Phoenix, Phoenix is so small that there is only one city that is responsible for the production of daily goods, and uses the road network to transport the goods to the capital. Ikki finds that the biggest problem in the country is that transportation speed is too slow.

Since Ikki was an ACM/ICPC contestant before, he realized that this, indeed, is a maximum flow problem. He coded a maximum flow program and found the answer. Not satisfied with the current status of the transportation speed, he wants to increase the transportation ability of the nation. The method is relatively simple, Ikki will reconstruct some roads in this transportation network, to make those roads afford higher capacity in transportation. But unfortunately, the country of Phoenix is not so rich in GDP that there is only enough money to rebuild one road. Ikki wants to find such roads that if reconstructed, the total capacity of transportation will increase.

He thought this problem for a loooong time but cannot get it. So he gave this problem to frkstyc, who put it in this POJ Monthly contest for you to solve. Can you solve it for Ikki?

Input

The input contains exactly one test case.

The first line of the test case contains two integers NM (N ≤ 500, M ≤ 5,000) which represents the number of cities and roads in the country, Phoenix, respectively.

M lines follow, each line contains three integers abc, which means that there is a road from city a to city b with a transportation capacity of c (0 ≤ ab < nc ≤ 100). All the roads are directed.

Cities are numbered from 0 to n − 1, the city which can product goods is numbered 0, and the capital is numbered n − 1.

Output

You should output one line consisting of only one integer K, denoting that there are K roads, reconstructing each of which will increase the network transportation capacity.

Sample Input

2 10 1 1

Sample Output

1

Source

POJ Monthly--2007.03.04, Ikki



题意:给出一个有向图,找这样一种边的个数,就是增加该边的容量,可以使得最大流变大。

题解:有两种做法:

1.先跑一遍最大流,得到残流图,然后枚举每一条每一条边,若该条边是要求的边,首先他应该是满流边,即残流为0,然后可以将这条边残流加1,再用bfs判能否找到增广路,如果可以,那么就是要求的边。


2.第二种方法基于这样一个事实,如果一条边是满流边,而且这条边的两个端点都能分别找到到起点和终点的非满流路径,那么这条边是关键边,即为所求。所以先跑一遍最大流,得到残流图, 然后分别从起点和终点沿着非满流边进行bfs,看每个点能否到达起点或终点,然后枚举每一条边,首先要求这条边是满流边,然后边的起点要能到达起点,边的终点要能到达终点,如果可以,那么这条边就是所求的边。


方法1代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std;const int MAXN=550;//点数的最大值const int MAXM=5500*2;//边数的最大值const int INF=0x3f3f3f3f;struct Node{    int from,to,next;    int cap,before;}edge[MAXM];int tol;int dep[MAXN];//dep为点的层次int head[MAXN];void init(){    tol=0;    memset(head,-1,sizeof(head));}void addedge(int u,int v,int w)//第一条边下标必须为偶数{    edge[tol].from=u;    edge[tol].to=v;    edge[tol].cap=w;    edge[tol].before=w;    edge[tol].next=head[u];    head[u]=tol++;    edge[tol].from=v;    edge[tol].to=u;    edge[tol].cap=0;    edge[tol].before=0;    edge[tol].next=head[v];    head[v]=tol++;}int BFS(int start,int end){    int que[MAXN];    int front,rear;    front=rear=0;    memset(dep,-1,sizeof(dep));    que[rear++]=start;    dep[start]=0;    while(front!=rear)    {        int u=que[front++];        if(front==MAXN)front=0;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v=edge[i].to;            if(edge[i].cap>0&&dep[v]==-1)            {                dep[v]=dep[u]+1;                que[rear++]=v;                if(rear>=MAXN)rear=0;                if(v==end)return 1;            }        }    }    return 0;}int dinic(int start,int end){    int res=0;    int top;    int stack[MAXN];//stack为栈,存储当前增广路    int cur[MAXN];//存储当前点的后继    while(BFS(start,end))    {        memcpy(cur,head,sizeof(head));        int u=start;        top=0;        while(1)        {            if(u==end)            {                int min=INF;                int loc;                for(int i=0;i<top;i++)                  if(min>edge[stack[i]].cap)                  {                      min=edge[stack[i]].cap;                      loc=i;                  }                for(int i=0;i<top;i++)                {                    edge[stack[i]].cap-=min;                    edge[stack[i]^1].cap+=min;                }                res+=min;                top=loc;                u=edge[stack[top]].from;            }            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)              if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])                 break;            if(cur[u]!=-1)            {                stack[top++]=cur[u];                u=edge[cur[u]].to;            }            else            {                if(top==0)break;                dep[u]=-1;                u=edge[stack[--top]].from;            }        }    }    return res;}int main(){int n,m;while(~scanf("%d%d",&n,&m)){init();while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);u++,v++;addedge(u,v,w);}dinic(1,n);int ans=0;for(int u=1;u<=n;u++){for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap==0&&edge[i].before){edge[i].cap+=1;if(BFS(1,n)) ans++;edge[i].cap-=1;}}}printf("%d\n",ans);}return 0;}


至于第二种解法,我至今还没ac。。。附上一个ac代码吧。

AC代码


0 0
原创粉丝点击