hdu 5294 Tricks Device(15多校第一场1007)(spfa+最小割)

来源:互联网 发布:通讯录医生是什么软件 编辑:程序博客网 时间:2024/06/04 19:16
//最小割+spfa#include<cstdio>#include<cstring>#include<queue>using namespace std;typedef long long LL;#define MIN(a,b) a<b?a:b#define MAX(a,b) a>b?a:bconst int N=50000,M=500000,INF=0x3fffffff;int n,m;struct EDGE{    int from,to,cap,next;}edge[M],edge2[M];int head[N];int cnt;void addedge(int u,int v,int w){    edge[cnt].from=u;edge[cnt].to=v;edge[cnt].cap=w;edge[cnt].next=head[u];    head[u]=cnt++;}void addedge2(int u,int v,int w){    edge2[cnt].from=u;edge2[cnt].to=v;edge2[cnt].cap=w;edge2[cnt].next=head[u];    head[u]=cnt++;}int dist[N][2];int step[N];int vis[N];void SPFA(int st,int num){    for(int i=0;i<=n;i++)dist[i][num]=INF,step[i]=INF;    memset(vis,0,sizeof(vis));    queue<int>q;    q.push(st);    dist[st][num]=0;    step[st]=0;vis[st]=1;    while(!q.empty()){        int k=q.front();        q.pop();vis[k]=0;        for(int i=head[k];i!=-1;i=edge[i].next){            int v=edge[i].to;            if(dist[k][num]+edge[i].cap<dist[v][num]){                dist[v][num]=dist[k][num]+edge[i].cap;                step[v]=step[k]+1;                if(!vis[v]){                    q.push(v);                    vis[v]=1;                }            }            else if(dist[k][num]+edge[i].cap==dist[v][num]){                step[v]=MIN(step[v],step[k]+1);            }        }    }}int q[N];int dep[N];//dep为距离编号int gap[N];//gap[x]=y:说明残留网络中dep[i]==x的节点有y个struct SAP{    int sum;    int src,des;    void init(){        src = 1;        des = n;    }    void bfs(int start,int end){        memset(dep, -1, sizeof(dep));        memset(gap, 0, sizeof(gap));        memset(q,-1,sizeof(q));        gap[0]=1;        int front,rear;        front=rear=0;        dep[end]=0;        q[rear++]=end;        while(front!=rear){            int u=q[front++];            if(front==N)front=0;            for(int i=head[u];i!=-1;i=edge2[i].next){                int v=edge2[i].to;                if(dep[v]!=-1)continue;                q[rear++]=v;                if(rear==N)rear=0;                dep[v]=dep[u]+1;                ++gap[dep[v]];            }        }    }    int Maxflow(){        int res=0;        bfs(src,des);        int cur[N],stack[N];        int top=0;        memcpy(cur,head,sizeof(head));        int u=src;        int i;        while(dep[src]<n){//如果src找不到一个可达点,则dep[src] = n + 1自动退出            if(u==des){//找到汇点                int temp=INF,inser=n;                for(int i=0;i<top;i++){//找从src点到des点的所有边中的最容量为temp,而那条边的编号为insert                    if(temp>edge2[stack[i]].cap){                        temp=edge2[stack[i]].cap;                        inser=i;                    }                }                for(int i=0;i<top;i++){//将正向边-temp,反向变+temp                    edge2[stack[i]].cap-=temp;                    edge2[stack[i]^1].cap+=temp;                }                res+=temp;//总的流量加temp                top=inser;//stack只保留从src到最小边insert“前向点”之间的边的信息,即insert边以后的边信息都不要                u=edge2[stack[top]].from;////u为insert的”前向点“            }                        for(i=cur[u];i!=-1;i=edge2[i].next){////当没有断层,找出一个可达边                if(edge2[i].cap!=0&&dep[u]==dep[edge2[i].to]+1)break;            }            if(i!=-1)//找到这个可达边,只能走到dep[u]-1;            {                cur[u]=i;//优化下次找dep[u] - 1不用从头开始找了                stack[top++]=i;                u=edge2[i].to;            }            else{//当没有找到深度为dep[u] - 1的可达边,那只能找深度更大的边                if(--gap[dep[u]]==0)break;   //出现断层,无增广路;                int minn = n;             //从头开始找出深度最小的可达边                for(i=head[u];i!=-1;i=edge2[i].next){                    if(edge2[i].cap==0)continue;                    if(minn>dep[edge2[i].to]){                        minn=dep[edge2[i].to];                        cur[u]=i;                    }                }                dep[u]=minn+1;//更新深度                ++gap[dep[u]];                if(u!=src)//如果u不是源点,还得回溯到dep[u] + 1(这里的dep[u]!=minn + 1)层,并将dep[u]层点全部修改变大。一直回溯到源点                    u=edge2[stack[--top]].from;            }        }        return res;    }};SAP sap;int main(){    while(scanf("%d%d",&n,&m)!=EOF){        cnt=0;        memset(head,-1,sizeof(head));                for(int i=0;i<m;i++){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w);            addedge(v,u,w);        }        SPFA(1,0);        int ans=step[n];        SPFA(n,1);        int len=dist[n][0];                cnt=0;        memset(head,-1,sizeof(head));                for(int i=0;i<2*m;i+=2){//重新建图            int u=edge[i].from,v=edge[i].to;            if(dist[u][0]+edge[i].cap+dist[v][1]==len){                addedge2(u,v,1);                addedge2(v,u,0);            }            else if(dist[u][1]+edge[i].cap+dist[v][0]==len){                addedge2(v,u,1);                addedge2(u,v,0);            }        }        sap.init();        printf("%d %d\n",sap.Maxflow(),m-ans);    }    return 0;}

0 0
原创粉丝点击