spoj 839最小割

a 夏天 提交于 2019-12-31 21:44:41

题意:给出一个无向图, 图中的一些点有mark值, 每条边<u,v>的权值为mark[u]^mark[v],  现在给出了一些点的mark值,现在想让你求出其他点的mark值让边权和最小。 点的个数100, 边的的个数为3000

思路: 对于mark值不同位的值是不影响的,所以可以一位一位的处理。对于每一位只能是1和0,对不不知道的点的mark只能是1和0,所以最后的问题就是将这些点分到两个集合中。 两个点之间如果不是一个集合并且还有边的话那么答案就要花费1. 我们这样建图。 

对于当前位mark值为1的点建一个<s,u, INF>的边, 对于为0的点我们建立<u,t,INF>的边。 对于普通的边建立一个

<u,v,1>,<v,u,1>的边。 让割最小就行。这样就转化成了最大刘德问题。

AC代码:

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <string>
  5 #include <iostream>
  6 using namespace std;
  7 const int N = 600, M = 30010, INF=1<<29;
  8 struct EDGE
  9  {
 10      int u, v, cap, next;
 11  }edge[M], p[M];
 12 
 13 int num, head[N], mark[N], ans[N];
 14 int gap[N], dis[N], pre[N], cur[N];
 15 int n, m;
 16 bool used[N];
 17 
 18 void init()
 19  {
 20      int u, w, k;
 21      scanf("%d%d", &n, &m);
 22      for(int i=0; i<m; i++)
 23       {
 24           scanf("%d%d", &p[i].u, &p[i].v);
 25       }
 26      memset(mark, -1, sizeof(mark));
 27      memset(ans, 0, sizeof(ans));
 28      scanf("%d", &k);
 29      while(k--)
 30       {
 31           scanf("%d%d", &u, &w);
 32           mark[u] = w;
 33       }
 34  }
 35 
 36 void add(int u, int v, int w)
 37  {
 38      edge[num].u = u;
 39      edge[num].v = v;
 40      edge[num].cap = w;
 41      edge[num].next = head[u];
 42      head[u] = num++;
 43  }
 44 
 45 void build(int k)
 46  {
 47      for(int i=1; i<=n; i++)
 48       {
 49           if(mark[i] != -1)
 50            {
 51                if(mark[i]&(1<<k))
 52                 {
 53                     add(0, i, INF);
 54                     add(i, 0, 0);
 55                 }
 56                else
 57                 {
 58                    add(i, n+1, INF);
 59                    add(n+1, i, 0);
 60                 }
 61            }
 62       }
 63      for(int i=0; i<m; i++)
 64       {
 65           add(p[i].u, p[i].v, 1);
 66           add(p[i].v, p[i].u, 0);
 67           add(p[i].v, p[i].u, 1);
 68           add(p[i].u, p[i].v, 0);
 69       }
 70  }
 71 
 72  int SAP(int s,int t) //sap模版
 73   {
 74     memset(gap,0,sizeof(gap));
 75     memset(dis,0,sizeof(dis));
 76     int i;
 77     for(i=0; i<=t;i++)
 78     {
 79         cur[i] = head[i];
 80     }
 81     int top=s;
 82     gap[s]=t+1;
 83     long long  maxflow=0,flow=M;
 84     while(dis[s] < t+1)
 85     {
 86         for(i=cur[top];i != -1;i = edge[i].next)
 87         {
 88             if(edge[i].cap > 0 && dis[top] == dis[edge[i].v] + 1)
 89                 break;
 90         }
 91         if(i != -1)
 92         {
 93             cur[top] = i;
 94             int v = edge[i].v;
 95             if(edge[i].cap < flow)
 96             {
 97                 flow = edge[i].cap;
 98             }
 99             top = v;
100             pre[v] = i;
101             if(top == t)
102             {
103                 maxflow += flow;
104                 while(top != s)
105                 {
106                     edge[pre[top]].cap -= flow;
107                     edge[pre[top]^1].cap += flow;
108                     top = edge[pre[top]^1].v;
109                 }
110                 flow = M;
111             }
112         }
113         else
114         {
115             if(--gap[dis[top]] == 0)
116             {
117                 break;
118             }
119             dis[top] = t+1;
120             cur[top] = head[top];
121             for(int j=head[top];j != -1;j=edge[j].next)
122             {
123                 if(edge[j].cap > 0 && dis[edge[j].v] + 1 < dis[top])
124                 {
125                     dis[top] = dis[edge[j].v] + 1;
126                     cur[top] = j;
127                 }
128             }
129             gap[dis[top]]++;
130             if(top != s)
131             {
132                 top = edge[pre[top]^1].v;
133             }
134         }
135     }
136     return maxflow;
137   }
138 
139 void dfs(int u, int k)
140  {
141      int v;
142      if(u>=1 && u<=n)
143       {
144           ans[u] |= (1<<k);
145       }
146      used[u] = 1;
147      for(int i=head[u]; i!=-1; i=edge[i].next)
148       {
149          if(edge[i].cap>0 && !used[edge[i].v])
150           {
151               dfs(edge[i].v, k);
152           }
153       }
154  }
155 
156 void solve()
157  {
158      for(int i=0; i<32; i++)
159       {
160           num = 0;
161           memset(head, -1, sizeof(head));
162 
163           build(i);
164           SAP(0,n+1);
165           memset(used, 0, sizeof(used));
166           dfs(0,i);
167       }
168      for(int i=1; i<=n; i++)
169      {
170          printf("%d\n", ans[i]);
171      }
172  }
173 
174 int main()
175  {
176      int t;
177      scanf("%d", &t);
178      while(t--)
179       {
180           init();
181           solve();
182       }
183      return 0;
184  }

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!