【NEERC 2003】有向图破坏
【题目描述】
Alice和Bob正在玩如下的游戏。首先Alice画一个有N个顶点,M条边的有向图。然后Bob试着摧毁它。在一次操作中他可以找到图中的一个点,并且删除它所有的入边或所有的出边。
Alice给每个点定义了两个值:Wi+和Wi-。如果Bob删除了第i个点所有的入边他要给Alice付Wi+元,如果他删除了所有的出边就需要给Alice付Wi元。
找到Bob删除图中所有边需要的最小花费。
【输入格式】
输入数据描述了Alice画下的图。
输入文件的第一行有两个数N,M(1<=N<=100,1<=M<=5000)。第二行有N个整数,描述了N个点的Wi+,同样的第三行是这N个点的Wi-。所有的费用都是正数并且不超过10^6。接下来的M行每行有两个数,代表有向图中相应的一条边。
【输出格式】
输出一行一个整数,即Bob的最小花费。
【分析】
很容易想到,把每个点拆成两个点,一个控制出边,一个控制入边,保留原边后很明显的一个最小权点覆盖集,Dinic就行了。
1 #include <cstdlib> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 const int maxn=500; 7 const int INF=10000*10000; 8 using namespace std; 9 struct tu 10 { 11 int c,f; 12 tu(){c=0;f=0;} 13 }maps[maxn][maxn]; 14 int dist[maxn],n,m; 15 16 void Dinic(); 17 bool BFS();//构建层次网络 18 int dfs(int v,int low); 19 20 int main() 21 { 22 int i; 23 //文件操作 24 freopen("destroyingthegraph.in","r",stdin); 25 freopen("destroyingthegraph.out","w",stdout); 26 memset(maps,0,sizeof(maps)); 27 28 scanf("%d%d",&n,&m);//n个点,m条边 29 30 for (i=1;i<=n;i++) scanf("%d",&maps[i+n][2*n+1].c);//w+ 31 for (i=1;i<=n;i++) scanf("%d",&maps[0][i].c);//w- 32 33 for (i=1;i<=m;i++) 34 { 35 int u,v; 36 scanf("%d%d",&u,&v); 37 maps[u][v+n].c=INF; 38 } 39 Dinic(); 40 return 0; 41 } 42 void Dinic() 43 { 44 int flow=0; 45 while ( BFS() ) 46 { 47 int temp=0; 48 if (temp=dfs(0,INF)) flow+=temp; 49 } 50 printf("%d\n",flow); 51 } 52 bool BFS()//层次网络 53 { 54 queue<int>Q; 55 int i; 56 memset(dist,-1,sizeof(dist)); 57 dist[0]=0; 58 Q.push(0); 59 while (!Q.empty()) 60 { 61 int u=Q.front();Q.pop(); 62 for (i=0;i<=(2*n+1);i++) 63 { 64 int v=i; 65 if(maps[u][v].c-maps[u][v].f>0 && dist[v]==-1) 66 { 67 dist[v]=dist[u]+1; 68 Q.push(v); 69 } 70 } 71 } 72 return (dist[(2*n)+1]!=-1); 73 } 74 int dfs(int u,int low) 75 { 76 if (u==(2*n)+1 || low==0) return low; 77 int flow=0,f,i; 78 for (i=0;i<=(2*n)+1;i++) 79 { 80 int v=i; 81 if (maps[u][v].c>maps[u][v].f && dist[v]==dist[u]+1) 82 { 83 if (f=dfs(i,min(low,maps[u][v].c-maps[u][v].f))) 84 { 85 maps[u][v].f+=f; 86 maps[v][u].f-=f; 87 low-=f; 88 flow+=f; 89 if (low==0) break; 90 } 91 } 92 } 93 return flow; 94 }