USACO Section 4.4 Pollutant Control

来源:互联网 发布:诺基亚e63怎样下载软件 编辑:程序博客网 时间:2024/05/01 23:17

题意:

一幅图求最小割  要求: 1、它是最小割(废话- -b) 2、割边数最少  3、割边字典序最小


思路:

对于要求1没啥说的直接最大流…

对于要求2可以想象为又是一个最小割问题(最少的边数割嘛)  于是把边权改为1再最大流

对于要求3按顺序枚举边(这样结果字典序一定最小)

如果这条边在要求1中是满流边  那么把它删掉  求要求2的最大流  如果最大流正好减少1  则这条边是答案

这样做的理由是  该边满足要求1  即它属于原图的一个最小割  同时要求2的最大流减少1说明也满足要求2


PS:

这尼玛是我遇见的第一道卡Dinic的题!!  用SAP速度快的飞起 - -b


代码:

/*ID: housera1PROG: milk6LANG: C++*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,ans;const int MAXN=40;const int MAXM=2010;const int INF=0x3f3f3f3f;struct Node{    int from,to,next,man,flag;    int cap;}edge[MAXM];int tol;int head[MAXN];int dep[MAXN];int gap[MAXN];void addedge(int u,int v,int w){    edge[tol].from=u;    edge[tol].to=v;    edge[tol].cap=w;    edge[tol].next=head[u];    head[u]=tol++;    edge[tol].from=v;    edge[tol].to=u;    edge[tol].cap=0;    edge[tol].next=head[v];    head[v]=tol++;}void BFS(int start,int end){    memset(dep,-1,sizeof(dep));    memset(gap,0,sizeof(gap));    gap[0]=1;    int que[MAXN];    int front,rear;    front=rear=0;    dep[end]=0;    que[rear++]=end;    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(dep[v]!=-1)continue;            que[rear++]=v;            if(rear==MAXN)rear=0;            dep[v]=dep[u]+1;            ++gap[dep[v]];        }    }}int SAP(int start,int end){    int res=0;    BFS(start,end);    int cur[MAXN];    int S[MAXN];    int top=0;    memcpy(cur,head,sizeof(head));    int u=start;    int i;    while(dep[start]<n)    {        if(u==end)        {            int temp=INF;            int inser;            for(i=0;i<top;i++)               if(temp>edge[S[i]].cap)               {                   temp=edge[S[i]].cap;                   inser=i;               }            for(i=0;i<top;i++)            {                edge[S[i]].cap-=temp;                edge[S[i]^1].cap+=temp;            }            res+=temp;            top=inser;            u=edge[S[top]].from;        }        if(u!=end&&gap[dep[u]-1]==0)          break;        for(i=cur[u];i!=-1;i=edge[i].next)           if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)             break;        if(i!=-1)        {            cur[u]=i;            S[top++]=i;            u=edge[i].to;        }        else        {            int min=n;            for(i=head[u];i!=-1;i=edge[i].next)            {                if(edge[i].cap==0)continue;                if(min>dep[edge[i].to])                {                    min=dep[edge[i].to];                    cur[u]=i;                }            }            --gap[dep[u]];            dep[u]=min+1;            ++gap[dep[u]];            if(u!=start)u=edge[S[--top]].from;        }    }    return res;}void solve(){    int i,j,ff;    for(i=0;i<tol;i+=2)    {        if(!edge[i].man) continue;        for(j=0;j<tol;j+=2)        {            if(!edge[j].flag) edge[j].cap=1;            edge[j^1].cap=0;        }        edge[i].cap=0;        edge[i].flag=1;        j=SAP(1,n);        if(j==ans-1)        {            ans--;            printf("%d\n",i/2+1);        }        else edge[i].flag=0;    }}int main(){    int Debug=0;    if(!Debug)    {        freopen("milk6.in","r",stdin);        freopen("milk6.out","w",stdout);    }    int i,u,v,w;    memset(head,-1,sizeof(head));    scanf("%d%d",&n,&m);    for(i=1;i<=m;i++)    {        scanf("%d%d%d",&u,&v,&w);        addedge(u,v,w);    }    printf("%d ",SAP(1,n));    for(i=0;i<tol;i+=2)    {        if(!edge[i].cap) edge[i].man=1;        edge[i].cap=1;        edge[i^1].cap=0;    }    ans=SAP(1,n);    printf("%d\n",ans);    if(ans) solve();    return 0;}


0 0
原创粉丝点击