挑战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[maxm<<1],next[maxm<<1],first[maxn];
  6 int tot,T,tmd,head,tail,match[maxn],vis[maxn],fa[maxn],lst[maxn],mrk[maxn],q[maxn];
  7 int read(){
  8     int tmp=0;
  9     char ch=0;
 10     while(!isdigit(ch))ch=getchar();
 11     while(isdigit(ch)){
 12         tmp=tmp*10+ch-'0';
 13         ch=getchar();
 14     }
 15     return tmp;
 16 }
 17 void clr(){
 18     memset(first,0,sizeof(first));
 19     cnt=0;
 20     memset(match,0,sizeof(match));
 21     memset(vis,0,sizeof(vis));
 22 }
 23 void add(int st,int end){
 24     v[++cnt]=end;
 25     next[cnt]=first[st];
 26     first[st]=cnt;
 27 }
 28 void link(int a,int b){ add(a,b),add(b,a); }
 29 int gf(int x){ return fa[x]==x?x:gf(fa[x]); }
 30 void un(int a,int b){ fa[gf(a)]=gf(b); }
 31 int lca(int a,int b){
 32     tmd++;
 33     while(1){
 34         if(a){
 35             a=gf(a);
 36             if(vis[a]==tmd)return a;
 37             vis[a]=tmd;
 38             if(match[a])a=lst[match[a]];
 39             else a=0;
 40         }
 41         swap(a,b);
 42     }
 43 }
 44 void haha(int x,int p){
 45     while(x!=p){
 46         int a=match[x],b=lst[a];
 47         if(gf(b)!=p)lst[b]=a;
 48         if(mrk[a]==2)mrk[q[++tail]=a]=1;
 49         if(mrk[b]==2)mrk[q[++tail]=b]=1;
 50         un(x,a),un(a,b);
 51         x=b;
 52     }
 53 }
 54 void find(int s){
 55     for(int i=1;i<=tot;i++)
 56         lst[i]=mrk[i]=0,fa[i]=i;
 57     head=tail=0;
 58     q[++tail]=s,mrk[s]=1;
 59     while(head<tail){
 60         int x=q[++head];
 61         for(int e=first[x];e;e=next[e]){
 62             if(gf(v[e])==gf(x)||mrk[v[e]]==2||v[e]==match[x])continue;
 63             if(mrk[v[e]]==1){
 64                 int p=lca(x,v[e]);
 65                 if(gf(x)!=p)lst[x]=v[e];
 66                 if(gf(v[e])!=p)lst[v[e]]=x;
 67                 haha(x,p),haha(v[e],p);
 68             }
 69             else if(!match[v[e]]){
 70                 int nw;
 71                 lst[nw=v[e]]=x;
 72                 while(nw){
 73                     x=lst[nw];
 74                     int tmp=match[x];
 75                     match[x]=nw,match[nw]=x;
 76                     nw=tmp;
 77                 }
 78                 return;
 79             }
 80             else{
 81                 lst[v[e]]=x;
 82                 mrk[v[e]]=2;
 83                 mrk[q[++tail]=match[v[e]]]=1;
 84             }
 85         }
 86     }
 87 }
 88 int main(){
 89     scanf("%d",&T);
 90     while(T--){
 91         clr();
 92         int n,m,E;
 93         scanf("%d%d%d",&n,&m,&E);
 94         tot=n+3*m;
 95         for(int i=1;i<=E;i++){
 96             int a,b;
 97             scanf("%d%d",&a,&b);
 98             for(int j=1;j<=3;j++)
 99                 link(a,n+(b-1)*3+j);
100         }
101         for(int i=1;i<=m;i++)
102             link(n+(i-1)*3+1,n+(i-1)*3+2);
103         for(int i=1;i<=tot;i++)
104             if(!match[i])find(i);
105         int ans=0;
106         for(int i=1;i<=tot;i++)
107             if(match[i])ans++;
108         printf("%d
",ans/2-n);
109         for(int i=1;i<=n;i++)
110             printf("%d ",(match[i]-n-1)/3+1);
111         printf("
");
112     }
113     return 0;
114 }
View Code
原文地址:https://www.cnblogs.com/Ngshily/p/5182839.html