zoukankan      html  css  js  c++  java
  • CF1423N BubbleSquare Tokens 题解

    Codeforces
    Luogu
    Thanks To Lillia

    P.S.

    以下推理过程都是看完题解之后回想的。

    Description.

    给定一个图,每条边可以有 \(0\)\(1\)\(2\) 个金币,每个点可以有 \(0\)\(1\) 个金币。
    每个点的权值定义为它和它所有连边总金币个数,现在要让任意一条边两个端点的权值不同。

    Coding.

    首先考虑无解情况 假装没看到题目中没给无解情况输出
    发现必定有解。

    粗略证明:精确证明的话直接构造出来就证完了
    假设当前的点为 \(x\),它的度数为 \(\deg(x)\)
    首先,我们考虑当前这个点有几种不同的权值。
    必定是 \(2\deg(x)+2\) 种,因为最小是 \(0\) 最大是 \(2\deg(x)+1\)
    然后,我们考虑和他相邻的点至多有几种不同数。
    发现至多只有 \(\deg(x)\)
    所以我们从理论上证明了最后应该是有可行解的。

    然后我们考虑,上面的粗略证明中,界限放的很宽。
    种类数有 \(2\deg(x)\) 而不同的只有 \(\deg(x)\),考虑这个 \(2\) 有什么用。
    同时,如果没有这个 \(2\),我们仍然满足,因为 \(\deg(x)+2>\deg(x)+1\)
    所以我们可以利用这个 \(2\),具体的,我们首先先把所有边权值赋成 \(1\)
    然后,对于当前所需要构造的点,我们可以对它出边和出边指向的点一个 \(+1\) 一个 \(-1\),我们就可以在其他点权值不变的情况下把当前这个点任意 \(+1\)\(-1\)
    同时,考虑通过上面这种方法能得到的所有点总数是 \(\deg(x)+1\) 个,严格大于它不能等于的数。
    所以必定存在一个数和周围全都不一样,让当前这个点权值为这个数即可。
    总复杂度是 \(O(\sum_{i=1}^ndeg(i))=O(m)\) 的。

    实现细节:因为是双向边,我们可以强行定向,钦定边是从 \(i\) 指向 \(j\)\((i<j)\)

    Coding.

    点击查看弱小代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),bz=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) bz=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	bz?x=-x:x;
    }/*}}}*/
    struct edge{int to,id,nxt;}e[2000005];int n,m,et,head[12505],id[12505],nx[12505];
    int fr[1000005],tw[1000005],we[1000005],wp[12505],vl[12505];char vs[1012505];
    inline void adde(int x,int y,int id) {e[++et]=(edge){y,id,head[x]},head[x]=et;}
    int main()
    {
    	read(n),read(m);for(int i=1;i<=m;i++) {read(fr[i]),read(tw[i]);if(fr[i]<tw[i]) swap(fr[i],tw[i]);}
    	for(int i=1;i<=m;i++) adde(fr[i],tw[i],i),we[i]=1,vl[fr[i]]++,vl[tw[i]]++;
    	for(int x=1;x<=n;x++)
    	{
    		for(int i=head[x];i;i=e[i].nxt) if(!wp[e[i].to]) wp[e[i].to]++,we[e[i].id]--,vl[x]--;
    		for(int i=head[x];i;i=e[i].nxt) vs[vl[e[i].to]]=1;
    		for(int i=head[x];i;i=e[i].nxt) if(vs[vl[x]]) vl[x]++,wp[e[i].to]--,we[e[i].id]++;else break;
    		for(int i=head[x];i;i=e[i].nxt) vs[vl[e[i].to]]=0;
    	}
    	int cn=0;for(int i=1;i<=n;i++) cn+=wp[i];
    	printf("%d\n",cn);for(int i=1;i<=n;i++) if(wp[i]) printf("%d ",i);
    	putchar('\n');for(int i=1;i<=m;i++) printf("%d %d %d\n",fr[i],tw[i],we[i]);
    	return 0;
    }
    
  • 相关阅读:
    Command模式应用实践
    .Net中的设计模式——Strategy模式
    PetShop之ASP.NET缓存
    征求书名
    PetShop之业务逻辑层设计
    Buider模式应用实践
    公告:目前博客园书业出版小组的工作进度
    “AS3.0高级动画编程”学习:第二章转向行为(下)
    as3: this,stage,root的测试
    As3.0中的位图(Bitmap/BitmapData)编程
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15114720.html
Copyright © 2011-2022 走看看