• 【CF1252L】Road Construction(基环树,最大流)


    题意:给定一张n点n边无重边自环的无向图,刚开始每条边都没有被选择,每条边上有一个颜色集合,必须从中选择一种

    有K个工人,每个工人有颜色a[i],需要把工人分配到与其颜色相同的边上

    问是否能有一种使得n个点完全联通的方案,如果有则输出

    n,K<=2000

    思路:考虑n-1条边的树的弱化版,显然每条边都应该被选择,用颜色和边建图跑最大流即可

    n点n边的基环树的情况下需要把环抠出来,设环的大小为size,两个端点至少有一个在环中的为A集合,其余为B集合

    显然B集合中所有的边都需要被选取,A集合中至多只能选择size-1条

    可以另外加源或者汇限制A集合的流量,也可以先加入B集合中的所有边,先跑最大流,判断是否小于n-size,因为A集合至多只有size-1的流量

    两种方法都试过,都很快

    我猜题解里写的应该就是用最大流跑的匹配,没听说过有能跑这个多重匹配的新算法

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  200010
     13 #define M  1000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 #define fors(i) for(auto i:e[x]) if(i!=p)
     29 
     30 const int MOD=1e9+7,inv2=(MOD+1)/2;
     31       double eps=1e-6;
     32       int dx[4]={-1,1,0,0};
     33       int dy[4]={0,0,-1,1};
     34 
     35 int head[N],vet[N],len[N],nxt[N],inq[N],inc[N],a[N],
     36     flag[N],vis[N],stk[N],dis[N],p[N],c[N],match[N],
     37     tot,top,s,S,T,T1;
     38 
     39 VI b[N],co[N];
     40 
     41 int read()
     42 {
     43    int v=0,f=1;
     44    char c=getchar();
     45    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     46    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     47    return v*f;
     48 }
     49 
     50 ll readll()
     51 {
     52    ll v=0,f=1;
     53    char c=getchar();
     54    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     55    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     56    return v*f;
     57 }
     58 
     59 void add(int a,int b)
     60 {
     61     nxt[++tot]=head[a];
     62     vet[tot]=b;
     63     head[a]=tot;
     64 }
     65 
     66 void Add(int a,int b,int c)
     67 {
     68     nxt[++tot]=head[a];
     69     vet[tot]=b;
     70     len[tot]=c;
     71     head[a]=tot;
     72 
     73     nxt[++tot]=head[b];
     74     vet[tot]=a;
     75     len[tot]=0;
     76     head[b]=tot;
     77 }
     78 
     79 void findc(int u,int fa)
     80 {
     81     stk[++top]=u;
     82     inq[u]=vis[u]=1;
     83     int e=head[u];
     84     while(e)
     85     {
     86         int v=vet[e];
     87         if(!vis[v]) findc(v,u);
     88          else if(v!=fa&&inq[v])
     89          {
     90              int s=1,t=top;
     91              while(1)
     92              {
     93                  t--;
     94                  s++;
     95                  if(stk[t]==v) break;
     96              }
     97              if(s>=3)
     98              {
     99                 t=top;
    100                 while(1)
    101                 {
    102                     inc[stk[t]]=1;
    103                     t--;
    104                     if(stk[t]==v){inc[v]=1; break;}
    105                 }
    106 
    107              }
    108          }
    109         e=nxt[e];
    110     }
    111     inq[stk[top]]=0;
    112     top--;
    113 }
    114 
    115 int bfs()
    116 {
    117     queue<int> q;
    118     rep(i,1,s) dis[i]=-1;
    119     q.push(S),dis[S]=0;
    120     while(!q.empty())
    121     {
    122         int u=q.front();
    123         q.pop();
    124         int e=head[u];
    125         while(e)
    126         {
    127             int v=vet[e];
    128             if(len[e]&&dis[v]==-1)
    129             {
    130                 dis[v]=dis[u]+1;
    131                 q.push(v);
    132             }
    133             e=nxt[e];
    134         }
    135     }
    136     return dis[T]!=-1;
    137 }
    138 
    139 int dfs(int u,int aug)
    140 {
    141     if(u==T) return aug;
    142     int e=head[u],val=0,flow=0;
    143     while(e)
    144     {
    145         int v=vet[e];
    146         if(len[e]&&dis[v]==dis[u]+1)
    147         {
    148             int t=dfs(v,min(len[e],aug));
    149             if(!t)
    150             {
    151                 e=nxt[e];
    152                 continue;
    153             }
    154             flow+=t;
    155             aug-=t;
    156             len[e]-=t;
    157             len[e^1]+=t;
    158             if(!aug) break;
    159         }
    160         e=nxt[e];
    161     }
    162     if(!flow) dis[u]=-1;
    163     return flow;
    164 }
    165 
    166 int main()
    167 {
    168     int n=read(),K=read();
    169     int m=0;
    170     rep(i,1,n)
    171     {
    172         p[i]=read();
    173         int x=read();
    174         while(x--)
    175         {
    176             int y=read();
    177             b[i].pb(y);
    178             c[++m]=y;
    179         }
    180     }
    181     rep(i,1,K)
    182     {
    183         a[i]=read();
    184         c[++m]=a[i];
    185     }
    186     sort(c+1,c+m+1);
    187     int k=unique(c+1,c+m+1)-c-1;
    188     rep(i,1,n)
    189      for(int j=0;j<b[i].size();j++) b[i][j]=lower_bound(c+1,c+k+1,b[i][j])-c;
    190 
    191 
    192     rep(i,1,k) co[i].clear();
    193     rep(i,1,K)
    194     {
    195         a[i]=lower_bound(c+1,c+k+1,a[i])-c;
    196         co[a[i]].pb(i);
    197     }
    198 
    199     tot=0;
    200     rep(i,1,n)
    201     {
    202         add(i,p[i]);
    203         add(p[i],i);
    204     }
    205     findc(1,0);
    206     s=k+n,S=++s,T=++s;
    207     rep(i,1,s) head[i]=0;
    208     tot=1;
    209     int sz=0;
    210     rep(i,1,k) Add(S,i,co[i].size());
    211     rep(i,1,n)
    212      for(int j=0;j<b[i].size();j++) Add(b[i][j],i+k,1);
    213     rep(i,1,n)
    214      if(inc[i]==0||inc[p[i]]==0) Add(i+k,T,1);
    215       else sz++;
    216     int ans=0;
    217     while(bfs()) ans+=dfs(S,INF);
    218     if(ans<(n-1-(sz-1)))
    219     {
    220         printf("-1
    ");
    221         return 0;
    222     }
    223     rep(i,1,n)
    224      if(inc[i]&&inc[p[i]]) Add(i+k,T,1);
    225     while(bfs()) ans+=dfs(S,INF);
    226     if(ans<n-1) printf("-1
    ");
    227      else
    228      {
    229         rep(i,1,n) flag[i]=0;
    230         rep(i,1,k)
    231         {
    232             int e=head[i],j=0;
    233             while(e)
    234             {
    235                 int v=vet[e];
    236                 if(v>=k+1&&v<=k+n&&flag[v-k]==0&&!len[e])
    237                 {
    238                     j++;
    239                     if(j>(int)co[i].size()) break;
    240                     int t=co[i][j-1];
    241                     match[t]=v-k;
    242                     flag[v-k]=1;
    243                 }
    244                 e=nxt[e];
    245             }
    246         }
    247         rep(i,1,K) printf("%d %d
    ",match[i],p[match[i]]);
    248      }
    249 
    250 
    251     return 0;
    252 }
  • 相关阅读:
    Servlet生命周期
    DAO 开发模式的几个类
    Iterator用法
    mysql相似于oracle的to_char() to_date()方法
    Java Web页面跳转
    JSP 连接MySQL 5.1
    采用DOM进行表格的修改操作
    使用css让XML文件按照HTML的风格显示出来
    正则表达式Regular Expression
    什么是“堆”,"栈","堆栈","队列",它们的区别
  • 原文地址:https://www.cnblogs.com/myx12345/p/11808160.html
Copyright © 2020-2023  润新知