首页 > 其他分享 >D44 2-SAT+前缀优化+二分 CF587D Duff in Mafia

D44 2-SAT+前缀优化+二分 CF587D Duff in Mafia

时间:2024-08-15 19:37:35浏览次数:13  
标签:include Duff idx int mid CF587D Mafia

视频链接:

 

CF587D Duff in Mafia - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N=500005;
int head[N],idx,ne[N*6],to[N*6];
void add(int x,int y){
  to[++idx]=y;ne[idx]=head[x],head[x]=idx;
}
int dfn[N],low[N],stk[N],scc[N],top,tim,cnt;
int n,m;
struct E1{int x,y,col,val;}e1[N]; //读入的边
struct E{int col,x,op;};
vector<E> e[N]; //端点上的边
bool cmp(E x,E y){return x.col<y.col;}

int f(int x,int op){return (x+m*op);}
int p0(int x,int op){return x+m*(op?2:3);}
int p1(int x,int op){return x+m*(op?4:5);}

void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int i=head[x];i;i=ne[i]){
    int y=to[i];
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;)
      scc[y=stk[top--]]=cnt;
  }
}
bool check(int mid){
  memset(head,0,sizeof(head));
  memset(dfn,0,sizeof(dfn));
  memset(scc,0,sizeof(scc));
  memset(stk,0,sizeof(stk));
  idx=tim=top=cnt=0;
  
  for(int i=1;i<=n;i++){ //有相同端点的边 选j边则不选其他
    for(int j=0;j<e[i].size();j++){
      add(f(e[i][j].x,0),p0(e[i][j].x,e[i][j].op)); //向下
      add(p1(e[i][j].x,e[i][j].op),f(e[i][j].x,1)); //向下
      if(j!=0){
        add(p0(e[i][j-1].x,e[i][j-1].op),p0(e[i][j].x,e[i][j].op)); //向右
        add(p1(e[i][j].x,e[i][j].op),p1(e[i][j-1].x,e[i][j-1].op)); //向左            
        add(p0(e[i][j-1].x,e[i][j-1].op),f(e[i][j].x,1)); //向右下
        add(f(e[i][j].x,0),p1(e[i][j-1].x,e[i][j-1].op)); //向左下
      }
    }
  }
  for(int i=1;i<=n;i++){ //有相同端点 相同颜色的边 不选这条则选那条
    for(int j=1;j<e[i].size();j++){
      if(e[i][j-1].col==e[i][j].col){
        add(f(e[i][j-1].x,1),f(e[i][j].x,0));
        add(f(e[i][j].x,1),f(e[i][j-1].x,0));
      }
    }
  }
  for(int i=1;i<=m;i++) //边权>mid的边 不选它
    if(e1[i].val>mid) add(f(i,0),f(i,1));
  
  for(int i=1;i<=m*2;i++) if(!dfn[i]) tarjan(i);
  for(int i=1;i<=m;i++) if(scc[i]==scc[i+m]) return 0;
  return 1;
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=m;i++)
    scanf("%d%d%d%d",&e1[i].x,&e1[i].y,&e1[i].col,&e1[i].val);
  for(int i=1;i<=m;i++){
    e[e1[i].x].push_back({e1[i].col,i,0});
    e[e1[i].y].push_back({e1[i].col,i,1});
  }
  for(int i=1;i<=n;i++){
    sort(e[i].begin(),e[i].end(),cmp); //按颜色值排序
    for(int j=2;j<e[i].size();j++)
      if(e[i][j-2].col==e[i][j].col) //一个点上超过3条同色边
        return puts("No"),0;
  }
  
  int l=-1,r=1e9+1,mid; //二分边权
  while(l+1<r){
    mid=(l+r)>>1;
    check(mid)?r=mid:l=mid;
  }
  if(r==1e9+1) return puts("No"),0;
  if(r==0) return printf("Yes\n0 0"),0;
  check(r); //退出二分时 检测值可能不是r 故再Tarjan一遍
  puts("Yes"); vector<int> e;
  for(int i=1;i<=m;i++)
    if(scc[i]<scc[i+m]) e.push_back(i);
  printf("%d %d\n",r,e.size()); //最小权,匹配边数
  for(int i=0;i<e.size();i++)printf("%d ",e[i]);
}

 

标签:include,Duff,idx,int,mid,CF587D,Mafia
From: https://www.cnblogs.com/dx123/p/18335173

相关文章

  • c 语言之 Duff’s Device
    c语言之Duff’sDevice介绍实现原理例子优点缺点现代使用介绍Duff’sdevice是一种优化循环展开技术,用于提高数据复制或处理的效率。它通过将循环展开和switch-case语句结合在一起,减少了循环控制的开销。这个技术由TomDuff在1983年首次提出,用于在C语言中......
  • POI2008MAF-Mafia
    POI#基环树#贪心#Year2008一定是若干棵基环内向树,以下仅考虑一棵的情况最小值直接从下往上选,然后环上的为环的\(siz\)的一半最大值为\(n\)减去叶子个数,再特判环上剩下一个的情况//Author:xiaruizeconstintN=1e6+10;intn;inta[N];intdeg[N];intcnt=......
  • xss.pwnfunction-Mafia
     这个是利用的构造函数用source来获取构造函数的源码并转化成小写Function(/ALERT(1337)/.source.toLowerCase())()或parseInt(string,radix)string:要被解析的字符串。radix:解析时使用的基数(进制)。可选参数,默认为10。用parseint将alert转成进制这里为什么用30因为在......
  • CF348A Mafia 题解
    由于题目具有十分明显的单调性(若\(x\)局能满足要求,则\(>x\)局一定能满足;若\(x\)局无法满足要求,则\(<x\)局也无法满足),因此我们考虑进行二分答案。二分所需要的局数\(x\),设所有人想玩的总局数为\(S\),由题意可得\(S=\sum^{n}_{i=1}a_i\)。因为每局都会有\(1\)人主持,\(n......
  • Codeforces 587D Duff in Beach
    不难发现可以按长度为\(n\)分为段。考虑到\(l\)其实并没什么大用,只是说对于选出来的\(b_{1\simx}\)可以都整体移任意段,只需要保证在范围内就行了。进一步的,发现只需要看最后一个数的取值得到其最大可以在的段数即为\(d\),那么移动的方案数就为\(d-x+1\)。还有的一......
  • CF587E Duff as a Queen
    维护序列,支持:区间异或查询区间子集异或值种数(包含空集)\(n\le2\times10^5\),\(1\leq\le4\times10^4\),值域\([1,10^9]\),TL=7s.经典题。操作2相当于查询区间线性基大小。由于不能维护区间异或,作差分\(b_i=a_i\oplusa_{i-1}\)。可以得到\(a_i=\oplusb_1\oplu......
  • 安卓-PorterDuffXfermode
    一、当我们要实现两张图片之间的混合模式的时候经常会用到PorterDuffXfermode二、使用方法mPaint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.DST_IN));在mPa......
  • MAFIA:2-devoflow(mafia-sdn/p4demos/demos/2-devoflow)
    2.1-DevoFlowcounterswiththreshold-basednotification(Counters,Samples,Tags)阈值通过流表的参数的形式传到数据平面,存储在自定义的元数据当中。2.2-DevoFl......
  • MAFIA:1.1 - OpenFlow statistics (Counters, Timestamps)(mafia-sdn/p4demos/demos/1-o
    1.1-OpenFlowstatistics(Counters,Timestamps)解决的核心问题:如何统计一个流的持续时间如何实现一个操作只在数据包第一次出现的时候执行一次,之后再也不执行:设置默......
  • 【XSY2414】【CF587C】Duff in the Army(倍增lca)
    看到题目中\(a<=0\),自然就想到用暴力维护这个东东。设倍增数组\(fa[u][i]\)和\(minn[u][i]\),其中\(minn\)存的是一个结构体,结构体中包含两个东东:一个数组和这个数组中的元......