URAL 1277 浅谈无向图网络流约束建模方法

来源:互联网 发布:在淘宝卖护肤品 编辑:程序博客网 时间:2024/06/05 03:42

这里写图片描述
世界真的很大
网络流一般是有向图,但无向图的情况还是有的
建图方法其实也差不多
先看一下题:
description

一个犯罪团伙打算去偷一家美术馆,警察决定派K个人堵住所有从匪窝通向美术馆的道路,不过他们只能驻守在沿途顶点处而不能在匪窝或美术馆,且每个点都有一个需要警察驻守的最低人数Ri。问警察是否能完成任务。 N<=100 M<=10000

input

The first line of the input contains a single integer 0 < K ≤ 10000the number of policemen engaged to control the stations.The second line has four integers: N, M, S and F delimited with white-space character.N is the number of stations in the galaxy (the stations are numbered from 1 to N); 2 < N ≤ 100.M is the number of teleportation channels; 1 < M ≤ 10000.S is the number of the planet (and the station) where the museum is; 1 ≤ S ≤ N.F is the number of the planet (and the station) where the thieves’ refuge is; 1 ≤ F ≤ N.The next line contains N integers ( x 1, …, xN) separated with white-space characterthe number of policemen required to control each of the stations (∑ i=1 N xi ≤ 10000).Then M lines follow that describe the teleportation channels. Each of these lines contains a pair of space-delimited integers — the numbers of stations being connected by a channel. The channel system is designed so that it is possible to reach any station from any other one (probably it would require several channel transitions).

output

YES或者NO表示是否可行

对于点的限制条件我们一般将其转化为对边的限制条件
考虑将一个点i拆成i和i+1两个点,之间连一条容量为i点需要的警察数的边,入i的边连到i点,从i出去的边由i+n这个点连出
然后跑一边最小割,就是用最少的警察将图分为美术馆和贼窝两部分,这也是经典的最小割,模型了
比较最小割和警察数目的大小,输出YES或NO
值得注意的是美术馆和贼窝是不能有警察的,所以将这两个点拆点的时候要注意边权设成INF
其他没什么要注意的了
每条边建成双向边就行了
完整代码:

#include<stdio.h>#include<queue>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;struct edge{    int v,w,last;}ed[100010];queue <int> state;int head[100010],dis[100010];int n,m,S=0,T,K,ans=0,num=1;void add(int u,int v,int w){    num++;    ed[num].v=v;    ed[num].w=w;    ed[num].last=head[u];    head[u]=num;}void init(){    num=1,ans=0;    memset(head,0,sizeof(head));}bool bfs(){    memset(dis,-1,sizeof(dis));    while(!state.empty()) state.pop();    state.push(S);    dis[S]=0;    while(!state.empty())    {        int u=state.front();        state.pop();        for(int i=head[u];i;i=ed[i].last)        {            int v=ed[i].v;            if(dis[v]==-1&&ed[i].w>0)            {                dis[v]=dis[u]+1;                state.push(v);            }        }    }    if(dis[T]==-1) return false;    return true;}int dfs(int u,int low){    int a=0;    if(u==T || low==0) return low;    for(int i=head[u];i;i=ed[i].last)    {        int v=ed[i].v;        if(ed[i].w>0&&dis[v]==dis[u]+1)        {            int tmp=dfs(v,min(low,ed[i].w));            ed[i].w-=tmp,ed[i^1].w+=tmp;            a+=tmp;            low-=tmp;            if(low==0) return a;        }    }    if(low) dis[u]=-1;    return a;}int main(){    while(scanf("%d",&K)!=EOF)    {        init();        scanf("%d%d%d%d",&n,&m,&T,&S);        for(int i=1;i<=n;i++)        {            int w;            scanf("%d",&w);            if(i==S || i==T) w=INF;            add(i,i+n,w);            add(i+n,i,0);            add(i+n,i,w);            add(i,i+n,0);        }        for(int i=1;i<=m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            add(u+n,v,INF);            add(v,u+n,0);            add(v+n,u,INF);            add(u,v+n,0);        }        T+=n;        while(bfs())            ans+=dfs(S,INF);        if(ans>K) printf("NO\n");        else printf("YES\n");    }    return 0;}/*Whoso pulleth out this sword out of this stone and anvil is duly King of all England*/

嗯,就是这样

原创粉丝点击