【Foreign】猜测 [费用流]
猜测
Time Limit: 10 Sec Memory Limit: 256 MBDescription
Input
Output
Sample Input
3
1 1
1 2
2 1
Sample Output
3
explain:
(1,1),(1,1),(2,2)不是一个合法猜测(有相同的格子),因此不管怎么猜总是能全部猜中。
HINT
Main idea
给定了若干个标准点,用这些点的横纵坐标分为x集和y集,定义猜点表示从x集和y集中各选一个,不能猜出重复的点,问在所有合法方案中最少包含上述几个标准点。
Solution
我们看到了这道题目,考虑从费用流的方法下手。
我们从S->x集:容量为数字出现次数,费用为0;y集->T:容量为数字出现次数,费用为0;x集->y集:容量为1,若组合成了标准点则费用为1,否则为0。
然后我们这样连边,又由于题目要的是最少包含几个点,那么显然最小费用最大流就是答案了。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cstring>
5 #include<cstdlib>
6 #include<cmath>
7 using namespace std;
8
9 const int ONE = 2000001;
10 const int INF = 2147483640;
11
12 int n,x,y;
13 int S,T;
14 int E[1001][1001];
15 int next[ONE],first[ONE],go[ONE],pas[ONE],Fro[ONE],tot=1;
16 int from[ONE],q[1000001],dist[200001];
17 bool vis[ONE];
18 int tou,wei;
19 int Ans,w[ONE];
20 int li[ONE],li_num;
21
22 struct power
23 {
24 int x,y;
25 }a[ONE],time[ONE],Max;
26
27 int get()
28 {
29 int res,Q=1; char c;
30 while( (c=getchar())<48 || c>57)
31 if(c=='-')Q=-1;
32 if(Q) res=c-48;
33 while((c=getchar())>=48 && c<=57)
34 res=res*10+c-48;
35 return res*Q;
36 }
37
38 void Add(int u,int v,int liu,int z)
39 {
40 next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; pas[tot]=liu; Fro[tot]=u;
41 next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=-z; pas[tot]=0; Fro[tot]=v;
42 }
43
44 int Bfs()
45 {
46 memset(dist,63,sizeof(dist));
47 dist[S]=0; q[1]=S; vis[S]=1;
48 tou=0; wei=1;
49 while(tou<wei)
50 {
51 int u=q[++tou];
52 for(int e=first[u];e;e=next[e])
53 {
54 int v=go[e];
55 if(dist[v]>dist[u]+w[e] && pas[e])
56 {
57 dist[v]=dist[u]+w[e]; from[v]=e;
58 if(!vis[v])
59 {
60 q[++wei]=v;
61 vis[v]=1;
62 }
63 }
64 }
65 vis[u]=0;
66 }
67 return dist[T]!=dist[T+10];
68 }
69
70 void Deal()
71 {
72 int x=INF;
73 for(int e=from[T];e;e=from[Fro[e]]) x=min(x,pas[e]);
74 for(int e=from[T];e;e=from[Fro[e]])
75 {
76 pas[e]-=x;
77 pas[e^1]+=x;
78 Ans += w[e]*x;
79 }
80 }
81
82 int main()
83 {
84 n=get();
85 for(int i=1;i<=n;i++)
86 {
87 a[i].x=get(); a[i].y=get();
88 li[++li_num]=a[i].x; li[++li_num]=a[i].y;
89 }
90
91 sort(li+1,li+li_num+1);
92 li_num = unique(li+1,li+li_num+1) - li - 1;
93 S=0; T=2*li_num+1;
94
95 for(int i=1;i<=n;i++)
96 {
97 a[i].x = lower_bound(li+1,li+li_num+1, a[i].x) - li;
98 a[i].y = lower_bound(li+1,li+li_num+1, a[i].y) - li;
99 E[ a[i].x ][ a[i].y ] = 1;
100 time[a[i].x].x++; time[a[i].y].y++;
101 Max.x = max(Max.x, a[i].x); Max.y = max(Max.y, a[i].y);
102 }
103
104 for(int i=1;i<=Max.x;i++) if(time[i].x) Add(S,i,time[i].x,0);
105 for(int i=1;i<=Max.y;i++) if(time[i].y) Add(i+Max.x,T,time[i].y,0);
106
107 for(int i=1;i<=Max.x;i++)
108 if(time[i].x)
109 for(int j=1;j<=Max.y;j++)
110 if(time[j].y)
111 {
112 if(E[i][j]) Add(i,j+Max.x,1,1);
113 else Add(i,j+Max.x,1,0);
114 }
115
116 while(Bfs()) Deal();
117
118 printf("%d",Ans);
119
120 }