BZOJ2095[Poi2010] Bridges

来源:互联网 发布:苹果网络锁是什么意思 编辑:程序博客网 时间:2024/06/05 19:48

BZOJ2095[Poi2010] Bridges

Description

YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。

Input

输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。

Output

输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)

Sample Input

4 4

1 2 2 4

2 3 3 4

3 4 4 4

4 1 5 4

Sample Output

4

HINT

注意:通过桥为欧拉回路

Solution:

人生第一道网络流,竟然交给了欧拉回路…

对于这道题,首先最大风力最小,显然是要先二分答案,然后这就转化成了一个经典的问题:混合图的欧拉回路判定问题。在本博客欧拉回路一文中另有阐述,此处不再赘述。(此处采用的POI的题目要求输出了方案)

#include<stdio.h>#include<iostream>#include<stdlib.h>#include<string.h>#include<vector>#include<queue>#define mp(a,b,c) (Edge){a,b,c}#define M 2005#define INF 1000000000using namespace std;struct Edge{int to,c,rev;};int A[M],B[M],C[M],D[M],n,m,degreein[M],degreeout[M],S,T;struct Dinic{    int id[M],level[M];    vector<Edge>G[M];    void Init(){        for(int i=S;i<=T;i++)G[i].clear();    }    void Addedge(int s,int t,int c){        G[s].push_back(mp(t,c,G[t].size()));        G[t].push_back(mp(s,0,G[s].size()-1));    }    void BFS(int s){        queue<int>Q;        level[s]=0;        Q.push(s);        while(!Q.empty()){            int top=Q.front();Q.pop();            for(int i=0;i<G[top].size();i++){                int to=G[top][i].to;                if(G[top][i].c==0||level[to]!=-1)continue;                level[to]=level[top]+1;                Q.push(to);            }        }    }    int dfs(int s,int t,int f){        if(s==t)return f;        for(int &i=id[s];i<G[s].size();i++){            int to=G[s][i].to;            if(level[to]>level[s]&&G[s][i].c){                int d=dfs(to,t,min(f,G[s][i].c));                if(d){                    G[s][i].c-=d;                    G[to][G[s][i].rev].c+=d;                    return d;                }            }        }        return 0;    }    int maxflow(int s,int t){        int maxflow=0;        while(1){            memset(level,-1,sizeof(level));            memset(id,0,sizeof(id));            BFS(s);            if(level[t]==-1)return maxflow;            int f;            while(f=dfs(s,t,INF))maxflow+=f;        }    }}Dinic;bool check(int x){    int full=0;    memset(degreein,0,sizeof(degreein));    memset(degreeout,0,sizeof(degreeout));    Dinic.Init();    for(int i=1;i<=m;i++){        if(C[i]>x&&D[i]>x)return false;        if(C[i]>x&&D[i]<=x){            degreein[A[i]]++;            degreeout[B[i]]++;        }else{            degreein[B[i]]++;            degreeout[A[i]]++;            if(C[i]<=x&&D[i]<=x)Dinic.Addedge(A[i],B[i],1);        }    }    for(int i=1;i<=n;i++){        int x=abs(degreein[i]-degreeout[i]);        if(x&1)return false;        if(degreein[i]>degreeout[i])Dinic.Addedge(i,T,x/2);        else {Dinic.Addedge(S,i,x/2);full+=x/2;}    }    return Dinic.maxflow(S,T)==full;}int ID[M][M];int ans[M],sz=0;void Pf(int x){    for(int i=1;i<=n;i++){        if(!ID[x][i])continue;        int t=ID[x][i];        ID[x][i]=0;        Pf(i);        ans[++sz]=t;    }}int main(){    int L,R,res=-1;    scanf("%d %d",&n,&m);    S=0;T=n+1;    for(int i=1;i<=m;i++){        scanf("%d %d %d %d",&A[i],&B[i],&C[i],&D[i]);        if(i==1||C[i]<L)L=C[i];        if(i==1||C[i]>R)R=C[i];        if(D[i]<L)L=D[i];        if(D[i]>R)R=D[i];        ID[A[i]][B[i]]=ID[B[i]][A[i]]=i;    }    while(L<=R){        int mid=(L+R)>>1;        if(check(mid)){            res=mid;            R=mid-1;        }else L=mid+1;    }    if(res==-1)puts("NIE");    else{        printf("%d\n",res);        check(res);        for(int i=1;i<=m;i++){            if(C[i]>res)ID[A[i]][B[i]]=0;            if(D[i]>res)ID[B[i]][A[i]]=0;        }        for(int i=1;i<=n;i++)            for(int j=0;j<Dinic.G[i].size();j++){                int to=Dinic.G[i][j].to;                if(to==T||to==S||Dinic.G[i][j].c==1)continue;                ID[i][to]=0;            }        Pf(1);        for(int i=sz;i>=1;i--)            printf("%d%c",ans[i],i==1?'\n':' ');    }    return 0;}
0 0