UOJ 171 【WC2016】挑战NPC

  一开始还真没想到是一般图匹配这种模型(毕竟才会的带花树)

  把每一个盒子拆成3个,每一个可以放置进它的小球分别向这三个点连边,然后这三个点在连成一个三元环,最终答案就是小球数目-匹配数。

  由于是一般图,所以套一个带花树就可以了。

  

  NOTICE:寻找增广路时,应该从球先找起,这样子才保证了每个球有地方放置。

  


  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 10010
 10 #define llg long long
 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 12 llg n,m,sett,father[maxn],pre[maxn],match[maxn],vis[maxn],id[maxn],dl[maxn*10],head,tail,ans,T,totn,e;
 13 llg c[1000][1000];
 14
 15 vector<llg> a[maxn];
 16
 17 llg find(llg x){if (father[x]!=x) father[x]=find(father[x]); return father[x];}
 18
 19 llg lca(llg x,llg y)
 20 {
 21     sett++;
 22     while (vis[x]!=sett)
 23     {
 24         if (x)
 25         {
 26             x=find(x);
 27             if (vis[x]==sett) return x;
 28             vis[x]=sett;
 29             if (match[x]!=0) x=find(pre[match[x]]);
 30             else x=0;
 31         }
 32
 33             swap(x,y);
 34     }
 35     return x;
 36 }
 37
 38 void change(llg x,llg y,llg fa)
 39 {
 40     llg z;
 41     while (find(x)!=fa)
 42     {
 43         pre[x]=y; z=match[x];
 44         if (id[z]==1) {id[z]=0,dl[++tail]=z;}
 45         if (find(z)==z) father[z]=fa;
 46         if (find(x)==x) father[x]=fa;
 47         y=z; x=pre[y];
 48     }
 49 }
 50
 51 bool bfs(llg p)
 52 {
 53     llg x,w,v;
 54     for (llg i=1;i<=n;i++) id[i]=-1,father[i]=i;
 55     head=0,tail=1,dl[1]=p; id[p]=0;
 56     do
 57     {
 58         x=dl[++head],w=a[x].size();
 59         for (llg i=0;i<w;i++)
 60         {
 61             v=a[x][i];
 62             if (id[v]==-1)
 63             {
 64                 pre[v]=x;
 65                 id[v]=1;
 66                 if (!match[v])
 67                 {
 68                     llg last,t,now=v;
 69                     while (now!=0)
 70                     {
 71                         t=pre[now],last=match[t];
 72                         match[t]=now; match[now]=t;
 73                         now=last;// v=t;
 74                     }//把原lai的匹配和非匹配bian取反
 75                     return 1;
 76                 }
 77                 id[match[v]]=0,dl[++tail]=match[v];
 78             }
 79             else
 80                 if (id[v]==0 && find(v)!=find(x))
 81                 {
 82                     llg dad=lca(x,v);
 83                     change(x,v,dad);
 84                     change(v,x,dad);
 85                 }
 86         }
 87     }while (head!=tail);
 88     return 0;
 89
 90 }
 91
 92 void link(llg x,llg y) {a[x].push_back(y),a[y].push_back(x);}
 93
 94 void init()
 95 {
 96     for (llg i=1;i<=n;i++) a[i].clear(),vis[i]=match[i]=pre[i]=father[i]=id[i]=dl[i]=0;
 97     //for (llg i=1;i<=n;i++) for (llg j=1;j<=n;j++) c[i][j]=c[j][i]=0;
 98     scanf("%lld%lld%lld",&n,&m,&e);
 99     totn=n;
100     llg x,y;
101     for (llg i=1;i<=e;i++)
102     {
103         scanf("%lld%lld",&x,&y);
104
105         llg po=m*3+x;
106         link(po,y*3-2),link(po,y*3-1),link(po,y*3);
107         //a[x].push_back(y),a[y].push_back(x);
108     }
109     n=n+m*3;
110     for (llg i=1;i<=m;i++)
111     {
112         link(i*3-2,i*3-1),link(i*3-1,i*3),link(i*3,i*3-2);
113     }
114 }
115
116 void oupt()
117 {
118     cout<<ans-totn<<endl;
119     for (llg i=1;i<=totn;i++)
120     {
121         printf("%lld ",(match[3*m+i]-1)/3+1);
122     }
123     printf("\n");
124 }
125
126 int main()
127 {
128     //yyj("a");
129     cin>>T;
130     while (T--)
131     {
132         ans=0;
133         init();
134         for (llg i=n;i>1;i--)
135             if (!match[i] && bfs(i)) ans++;
136         oupt();
137     }
138     return 0;
139 }
时间: 2024-08-03 18:41:47

UOJ 171 【WC2016】挑战NPC的相关文章

[WC2016]挑战NPC 解题报告

[WC2016]挑战NPC 题意 有 \(n\) 个球, \(m\) 个筐, \(e\) 个条件 \((u,v)\), 表示球 \(u\) 可以放进筐 \(v\) 里面. 每个球都必须放进筐里, 每个筐最多可以放 \(3\) 个球, 如果一个筐里的球数不超过 \(1\), 则称这个筐是 半满 的. 求最多能使多少个筐半满, 并输出方案. 数据保证一定存在一种方案使得每个球都放进筐里. 思路 匹配问题. 把一个筐看做三个只能放一个球的篮. 一个筐要是 半满 的, 那它至少要有 \(2\) 个空着的

BZOJ4405 [wc2016]挑战NPC

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. 每个筐子最多能装3个球. 每个球只能放进特定的筐子中.具体有e个条件,第i个条件用两个整

[WC2016]挑战NPC

Sol 这做法我是想不到\(TAT\) 每个筐子拆成三个相互连边 球向三个筐子连边 然后跑一般图最大匹配 这三个筐子间最多有一个匹配 那么显然每个球一定会放在一个筐子里,一定有一个匹配 如果筐子间有匹配,则有一个半空的筐子,因为它一定只匹配了小于等于\(1\)个球 答案为匹配数\(-n\) 使答案最大即匹配数最大 上带花树就好了 # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a,

UOJ171 【WC2016】挑战NPC

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. 每个筐子最多能装3个球. 每个球只能放进特定的筐子中.具体有e个条件,第i个条件用两个整

挑战NPC

%%%VFK,神建图 题目要求“半空的”筐子数最多 我们把每个筐子拆成3个槽,两两连边,形成一个三元环.然后对读入的可行配对,由小球分别向三个筐子连边. 进行匹配时我们发现,三元环内会形成一条匹配边,当且仅当筐子为“半空的”. 这样就转化成了一般图最大匹配,Ans=最大匹配-n 学习了一个带花树 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 605 4 #define maxm 90105 5 int cnt,v

uoj #172. 【WC2016】论战捆竹竿

#172. [WC2016]论战捆竹竿 这是一个美好的下午,小 W 和小 C 在竹林里切磋捆竹竿的技艺. 竹林里有无数根完全一样的短竹子,每一根竹子由 nn 节组成. 这些竹子比较特别,每一节都被染上了颜色.可能的颜色一共 2626 种,分别用小写英文字母 a 到 z 表示.也就是说,如果把竹子的底端到顶端的颜色按顺序写出来可以排成一个由小写英文字母组成的字符串. 小 W 和小 C 都是捆竹竿的高手,他们知道怎样才能把零散的短竹子捆成一整根长竹竿.初始时你拿着一根短竹子作为当前的竹竿.每次你可以

codevs 2924 数独挑战 x(三种做法+超详细注释~)

2924 数独挑战 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题目描述 Description “芬兰数学家因卡拉,花费3个月时间设计出了世界上迄今难度最大的数独游戏,而且它只有一个答案.因卡拉说只有思考能力最快.头脑最聪明的人才能破解这个游戏.”这是英国<每日邮报>2012年6月30日的一篇报道.这个号称“世界最难数独”的“超级游戏”,却被扬州一位69岁的农民花三天时间解了出来. 看到这个新闻后,我激动不已,证明我们OI的实力的机会来了,我们虽然不是

[UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 n杯鸡尾酒.这 n杯鸡尾酒排成一行,其中第 i杯酒 (1≤i≤n ) 被贴上了一个标签 si ,每个标签都是 26 个小写英文字母之一.设 Str(l,r)表示第 l杯酒到第 r 杯酒的 r−l+1 个标签顺次连接构成的字

uoj#87. mx的仙人掌

1 //Achen 2 #include<bits/stdc++.h> 3 #define For(i,a,b) for(int i=(a);i<=(b);i++) 4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 5 #define Formylove return 0 6 const int N=2e6+7,mod=571111; 7 typedef long long LL; 8 typedef double db; 9 using