ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[cf587D]Duff in Mafia

2021-05-03 18:02:35  阅读:159  来源: 互联网

标签:Duff int back color add edge cf587D 2sat Mafia


二分最大边权,即有些边强制不能被选

接下来,即任意一点上某两边不能同时被选,以及任意一点上颜色相同的两边必须被选择一条

这些限制都可以用2-sat的形式来描述(强制不能选即连边"选->不选"),但后两类的边数达到了$o(m^{2})$,时间复杂度上无法接受

当一个节点上有一种颜色的边出现3次,或有两种颜色的边出现两次,必然不合法,因此第3类限制的边每一个点上至多只有1条,即为$o(n)$

对于第2类限制,即该点上任意一边都要向其余边连线,那么即新建一些点来优化连边

更具体的,假设某个点上相关的边分别对应点$a_{1},a_{2},...,a_{k}$和$a'_{1},a'_{2},...,a_{k}$(后者表示不选),即需要连边$(a_{i},a'_{j})$(其中$i\ne j$)

新建$s_{1},s_{2},...,s_{k}$,连边$(s_{i},s_{i-1})$和$(s_{i},a'_{i})$,再连边$(a_{i},s_{i-1})$即实现了连边$(a_{i},a'_{j})$(其中$j<i$)

对于$j>i$类似,即连边$(s'_{i},s'_{i+1})$和$(s'_{i},a'_{i})$,再连边$(a_{i},s'_{i+1})$即可

综上,即将边数优化为$o(m)$,可以通过

(关于这个,也可以理解为前后缀的构造)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 struct Edge{
  5     int nex,to,color,len;
  6 }edge[N];
  7 vector<int>v,ans,A[N*3],B[N*3];
  8 map<int,int>tot,lst;
  9 int V,E,n,m,x,y,c,z,scc,head[N],vis[N*3],dfn[N*3],bl[N*3];
 10 void add_edge(int x,int y,int c,int z){
 11     edge[E].nex=head[x];
 12     edge[E].to=y;
 13     edge[E].color=c;
 14     edge[E].len=z;
 15     head[x]=E++;
 16 }
 17 void add_2sat(int x,int y){
 18     A[x].push_back(y);
 19     B[y].push_back(x);
 20 }
 21 void del_2sat(int x,int y){
 22     A[x].pop_back();
 23     B[y].pop_back();
 24 }
 25 void dfs1(int k){
 26     if (vis[k])return;
 27     vis[k]=1;
 28     for(int i=0;i<A[k].size();i++)dfs1(A[k][i]);
 29     dfn[++dfn[0]]=k;
 30 }
 31 void dfs2(int k){
 32     if (bl[k])return;
 33     bl[k]=scc;
 34     for(int i=0;i<B[k].size();i++)dfs2(B[k][i]);
 35 }
 36 bool calc(int k){
 37     for(int i=0;i<E;i+=2)
 38         if (edge[i].len>k)add_2sat((i>>1),(i>>1)+m);
 39     scc=dfn[0]=0;
 40     memset(vis,0,sizeof(vis));
 41     memset(bl,0,sizeof(bl));
 42     for(int i=0;i<V;i++)
 43         if (!vis[i])dfs1(i);
 44     for(int i=dfn[0];i;i--)
 45         if (!bl[dfn[i]]){
 46             scc++;
 47             dfs2(dfn[i]);
 48         }
 49     bool flag=1;
 50     for(int i=0;i<m;i++)
 51         if (bl[i]==bl[i+m]){
 52             flag=0;
 53             break;
 54         }
 55     for(int i=0;i<E;i+=2)
 56         if (edge[i].len>k)del_2sat((i>>1),(i>>1)+m);
 57     return flag;
 58 }
 59 int main(){
 60     scanf("%d%d",&n,&m);
 61     memset(head,-1,sizeof(head));
 62     for(int i=1;i<=m;i++){
 63         scanf("%d%d%d%d",&x,&y,&c,&z);
 64         add_edge(x,y,c,z);
 65         add_edge(y,x,c,z);
 66     }
 67     V=(m<<1); 
 68     for(int i=1;i<=n;i++){
 69         x=y=-1;
 70         v.clear(),tot.clear(),lst.clear();
 71         for(int j=head[i];j!=-1;j=edge[j].nex){
 72             tot[edge[j].color]++;
 73             if (tot[edge[j].color]>2){
 74                 printf("No");
 75                 return 0;
 76             }
 77             if (tot[edge[j].color]==2){
 78                 if ((x>=0)&&(y>=0)){
 79                     printf("No");
 80                     return 0;
 81                 }
 82                 x=(lst[edge[j].color]>>1);
 83                 y=(j>>1);
 84             }
 85             lst[edge[j].color]=j;
 86             v.push_back(j>>1);
 87         }
 88         if ((x>=0)&&(y>=0)){
 89             add_2sat(x+m,y);
 90             add_2sat(y+m,x);
 91         }
 92         for(int j=0;j<v.size();j++){
 93             add_2sat(V+j,v[j]+m);
 94             add_2sat(V+j+v.size(),v[j]+m);
 95         }
 96         for(int j=1;j<v.size();j++){
 97             add_2sat(V+j,V+j-1);
 98             add_2sat(V+j+v.size()-1,V+j+v.size());
 99             add_2sat(v[j],V+j-1);
100             add_2sat(v[j-1],V+j+v.size());
101         }
102         V+=(v.size()<<1);
103     }
104     int l=0,r=0x3f3f3f3f;
105     while (l<r){
106         int mid=(l+r>>1);
107         if (calc(mid))r=mid;
108         else l=mid+1;
109     }
110     if (l==0x3f3f3f3f)printf("No");
111     else{
112         calc(l);
113         for(int i=0;i<m;i++)
114             if (bl[i]>bl[i+m])ans.push_back(i+1);
115         printf("Yes\n%d %d\n",l,ans.size());
116         for(int i=0;i<ans.size();i++)printf("%d ",ans[i]);
117     }
118 }
View Code

 

标签:Duff,int,back,color,add,edge,cf587D,2sat,Mafia
来源: https://www.cnblogs.com/PYWBKTDA/p/14727851.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有