首页 > 其他分享 >818 Div 2.F. Madoka and The First Session

818 Div 2.F. Madoka and The First Session

时间:2023-01-11 22:13:49浏览次数:64  
标签:cnt Madoka val int 818 maxn Div data first

Problem - F - Codeforces

818 Div 2.F. Madoka and The First Session

思路:

不妨转化一下题意:

将条件转化为:\(b_v+1,b_v+1\),然后使得其中一个-2

那么在\(a\)上就是使\(a_v-1,a_u-1\),然后使得其中一个+2

问能否使得\(a\)数组全部为0(仅仅只对于每个\(s_i\)为1)(因为这是倒推,相当于从\(a\)得到\(b\))

(由于当\(s_i\)为0时,其\(a_i\)不一定为准确值,那么倒推的值不一定为0)

我们可以先全部减完,那么无解的条件便是:对于每一个\(s_i\)为1时,存在\(a_i\)为奇数或\(a_i>0\)

显然,减完1之后我们只能加2,若a为奇数或大于0则必然不可能使得其变成0

于是乎,我们的问题就变成了如何安排+2

我们是知道每个数需要加多少次的,不妨构造网络流A集合(及左部)为边,B集合(即右部)为点。这样构造有什么好处?

原因在于每一条边+2的权利都只能用一次,我们从源点连向A集合每一个点,并使其容量为1便可以做到;

对于每一条边,我们会连接两个点,于是从A集合连向B集合,容量也为1,相当于是每个A部分的点都会连接两个B部分的点

对于B部分的点,分情况讨论:
若此点的\(s_i\)为1,那么就让其连向t,容量为其需要的次数

若此点的\(s_i\)为0,那么就让其连向\(mid\),\(mid\)为一个中介节点,目的是让其流量守恒,容量为无限大(反正它也没有限制)

最后,让\(mid\)连向\(t\),满足守恒之后,若满流则有解,直接输出答案即可;否则输出NO

时间复杂度:
边数:\(4m+1\)(大概) 点数:\(n+m\)

\(dinic\)在二分图上极为优秀,其时间复杂度为\(O(m\sqrt{n})\),足以通过此题

//
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int INF=0x3f3f3f3f;
int n,m,s,t,mid;
int S[maxn],A[maxn];
int l[maxn],r[maxn];
struct node{
    int data,nxt,val; 
}a[maxn];
int first[maxn];
int cnt=1;
int d[maxn],vis[maxn];
queue<int>q;
void add(int x,int y,int val){
    a[++cnt].data=y;
    a[cnt].val=val;
    a[cnt].nxt=first[x];
    first[x]=cnt;
    a[++cnt].data=x;
    a[cnt].val=0;
    a[cnt].nxt=first[y];
    first[y]=cnt;
}
int bfs(){
    memset(d,0,sizeof(d));
    while(q.size())q.pop();
    q.push(s);d[s]=1;;
    while(q.size()){
        int x=q.front();
        q.pop();
        for(int i=first[x];i!=0;i=a[i].nxt){
            int k=a[i].data;
            if(a[i].val&&!d[k]){
                q.push(k);
                d[k]=d[x]+1;
                if(k==t)return 1;
            }
        }
    }
    return 0;
}
int dinic(int x,int flow){
    if(x==t)return flow;
    int r=flow,k,i;
    for(i=first[x];i&&r;i=a[i].nxt){
        if(a[i].val&&d[a[i].data]==d[x]+1){
            k=dinic(a[i].data,min(r,a[i].val));
            if(!k)d[a[i].data]=0;
            a[i].val-=k;
            a[i^1].val+=k;
            r-=k;
        }
    }
    return flow-r;
}
int work(int x){
    for(int i=first[x];i;i=a[i].nxt){
        int k=a[i].data;
        if(k==s)continue;
        if(a[i^1].val){
            return k-m;
        }
    }
    return 114514;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)scanf("%d",&S[i]);
    for(int i=1;i<=n;i++)scanf("%d",&A[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&l[i],&r[i]);
        A[l[i]]--,A[r[i]]--;
    }
    for(int i=1;i<=n;i++){
        if((S[i]&&(A[i]&1))||A[i]>0){
            printf("NO\n");
            return 0;
        }
    }
    t=m+n+2;mid=n+m+1;
    for(int i=1;i<=m;i++)add(s,i,1);
    for(int i=1;i<=m;i++){
        add(i,l[i]+m,1);
        add(i,r[i]+m,1);
    }
    int v=0;
    for(int i=1;i<=n;i++){
        if(S[i]==1)add(i+m,t,-A[i]/2),v=v+(-A[i]/2);
        else add(i+m,mid,INF);
    }
    if(m-v<0){
        printf("NO\n");
        return 0;
    }
    add(mid,t,m-v);
    int ans=0;
    while(bfs())ans+=dinic(s,INF);
    if(ans!=m)printf("NO\n");
    else{
        printf("YES\n");
        for(int i=1;i<=m;i++){
            int x=work(i);
            if(x==r[i])printf("%d %d\n",r[i],l[i]);
            else printf("%d %d\n",l[i],r[i]);
        }
    }
    return 0;
}

标签:cnt,Madoka,val,int,818,maxn,Div,data,first
From: https://www.cnblogs.com/c20230507/p/17045027.html

相关文章

  • [Codeforces Round #822 (Div. 2)](https://codeforces.com/contest/1734)
    CodeforcesRound#822(Div.2)ProblemF.ZerosandOnes解法定义:\(f(x)\)为在\(S\)串中位置为\(x\)的值。显然\(f(x)\in0,1\)有一重要性质:若\(f(x)\)为1,那么二进制......
  • Codeforces Round #843 (Div. 2)
    Preface难得的7点场CF,结果反而遇上了我最困的时候(吃完晚饭血糖上来就贼困,我一般反而凌晨场比较清醒)但是这场表现还可以,写的题基本都是一发入魂而且速度也比较快比较可惜......
  • Codeforces Round #843 (Div. 2)
    A-GardenerandtheCapybaras题意给出字符串S,S只由字符a,b组成,问怎么切分可以使字符串分为小大小,大小大这种的三段。思路在2~n-1的范围内找到字符a的位置,如果里......
  • Codeforces Round #843 (Div. 2)
    题目链接Atag:构造,分类讨论核心思路我们其实可以发现我们要是分很多情况去讨论abc,这题就不好做。所以我们可以假设a和b就是我们字符串的两个端点,这样题目就很好做了......
  • Codeforces Round #843 (Div. 2) Problem C
    C.InterestingSequencetimelimitpertest1secondmemorylimitpertest256megabytesinputstandardinputoutputstandardoutput  Petyaandhisfr......
  • Codeforces Round #823 (Div. 2)
    A.B.C.DCodeforcesRound#823(Div.2)A.Planets-签到题意题意是一些卫星在一些轨道上,操作1花费1摧毁一个卫星,操作2花费\(y\)摧毁一个轨道上的所有卫星,问摧......
  • 一个CF1775C(Codeforces Round #843 (Div. 2))的小技巧
    若\(n\)的第\(i\)位为\(1\),而我们需要不断令\(n+1\)找到下一个最小的\(k\),使得\(k\)的第\(i\)位为\(0\)。技巧:假设\(n\)为10101[1]1001,括号内是要求的第\(i\)位那么先......
  • 海康NVR国标GB28181设备通道数为0设备不在线 解决办法
    最近搞国标平台需要用GB28181把各个监控中心摄像头汇聚到总部监控平台,期间遇到各种各样的问题。本文主要讲解海康威视NVR设备通过国标接入平台遇到的问题,给大家做参考,方便......
  • CF Codeforces Round #843 (Div. 2)
    CodeforcesRound#843(Div.2)本次脑袋不大灵光,一方面可能是怕掉分。另一方面就是交的人实在是太少了,导致我一直不敢交,其实这场cf没有我想象中那么难,甚至来说我一直是......
  • Codeforces Round #843 (Div. 2) 做题记录
    CodeforcesRound#843(Div.2)做题记录A1&A2.GardenerandtheCapybarasProblemCF1775A2GardenerandtheCapybaras题目大意:给你一个由a和b组成的字符串,要......