Description
为了剌激消费,学校给同学们发了一些优惠劵,上面都有两个神秘的数字A,B代表返钱的数字。其值在[1,10000]。每张优惠劵只能使用一次,而且只能使用A,B中的某个数字一次,且用完后优惠劵就回收了......太奇葩了吧。J老师觉得这样玩太简单了,现在假设某个同学手中有若干张优惠劵,J老师希望这个同学首先拿出一张优惠劵出来,上面必须有数字1,然后再拿出一张优惠劵出来,上面必须有数字2......小W听了后,马上拿出手中的优惠劵,盘算着这个游戏可以进行多少轮。
Input
输入的第一行是一个整数N,表示拥有N种优惠劵
接下来N行,是对这N种优惠劵描述,每行2个数字,表示第i种优惠劵上面的2个数字
N < =1000000
Output
如题
Sample Input
3
1 2
3 2
4 5
Sample Output
2
//先使用第一张中的1,再使用第二张中的2
sol:二分图匹配
图上部为优惠券数字,下部为优惠券。数字从1开始,为每一个数字找匹配的优惠券,如果某数字找不到匹配的优惠券了,匹配结束。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 const int maxn=1000010; 6 int n,cnt,ans; 7 int vis[maxn],from[maxn],to[maxn<<1],next[maxn<<1],val[maxn<<1],head[maxn]; 8 void add(int a,int b) 9 { 10 to[cnt]=b; 11 next[cnt]=head[a]; 12 head[a]=cnt++; 13 } 14 int dfs(int x) 15 { 16 int i; 17 for(i=head[x];i!=-1;i=next[i]) 18 { 19 if(vis[to[i]]==ans) continue; 20 vis[to[i]]=ans; 21 if(!from[to[i]]||dfs(from[to[i]])) 22 { 23 from[to[i]]=x; 24 return 1; 25 } 26 } 27 return 0; 28 } 29 int main() 30 { 31 scanf("%d",&n); 32 int i,a,b; 33 memset(head,-1,sizeof(head)); 34 for(i=1;i<=n;i++) 35 { 36 scanf("%d%d",&a,&b); 37 add(a,i),add(b,i); //添加边,将第i张优惠卷上的金额与i连边 38 } 39 for(ans=1;ans<=n;ans++) //枚举金额为i的优惠卷,由哪张优惠劵提供 40 { 41 if(!dfs(ans))//若当前匹配不成功了,游戏结束 42 { 43 printf("%d",ans-1);//输出满足条件的最大匹配 44 return 0; 45 } 46 } 47 printf("%d",n); 48 return 0; 49 }