zoukankan      html  css  js  c++  java
  • CF1186 F. Vus the Cossack and a Graph

    题目传送门:https://codeforces.com/problemset/problem/1186/F

    题目大意:
    给一个(n)(m)条边的无向简单图(G),记(d_i)为点(i)的度数。你需要在其中找到一个子图(Z),满足(Z)的边数(m_Zleqslant lceilfrac{n+m}{2} ceil),记(f_i)(Z)中点(i)的度数,满足(forall iin G,lceilfrac{d_i}{2} ceilleqslant f_i)

    求子图(Z)


    解法一(暴力+人品):将所有边存下来后随机打乱,然后判断端点度数是否满足(lfloorfrac{d_i}{2} floorleqslant f_i),进行加边与否的操作即可

    解法二(正解):

    • 所有点的度数都是偶数,说明该图存在欧拉回路,我们求出欧拉回路,然后间隔保留(frac{m}{2})条边,这样即可保证所有点的度数恰好为(f_i=frac{d_i}{2})

    • 存在部分点的度数为奇数,我们可以新建0号节点,向所有度数为奇数的点连边(虚边)。显然,这些点的数量为偶数,故新图所有点的度数都为偶数

      给新图求欧拉回路后,虚边会将回路分割成若干部分。若该段边数为偶数,则按上一种情况处理;如果该段边数为奇数,则保留两端的边,中间再间隔保留。因为两端的点的度数为奇数,需要多保留一位

    /*program from Wolfycz*/
    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define Fi first
    #define Se second
    #define ll_inf 1e18
    #define MK make_pair
    #define sqr(x) ((x)*(x))
    #define pii pair<int,int>
    #define int_inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>inline T frd(T x){
    	int f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    template<typename T>inline T read(T x){
    	int f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e6;
    int pre[(N<<2)+10],now[N+10],child[(N<<2)+10],vis[(N<<2)+10];
    int stack[(N<<2)+10],Ans[N+10][2],D[N+10],Cur[N+10],top,n,m,Cnt,tot=1;
    void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    void insert(int x,int y){join(x,y),join(y,x);}
    void Dfs(int x,int Fr){
    	for (;Cur[x];){
    		int p=Cur[x]; Cur[x]=pre[Cur[x]];
    		if (vis[p])	continue;
    		vis[p]=vis[p^1]=1;
    		Dfs(child[p],p);
    	}
    	if (Fr)	stack[++top]=Fr;
    }
    void solve(){
    	for (int i=1,Last=0;i<=top+1;i++){
    		if (i>top||stack[i]>(m<<1)+1){
    			for (int j=Last+1;j<i;j+=2){
    				Ans[++Cnt][0]=child[stack[j]];
    				Ans[Cnt][1]=child[stack[j]^1];
    			}
    			if ((i-Last)%2&&Last+1<i){
    				Ans[++Cnt][0]=child[stack[i-1]];
    				Ans[Cnt][1]=child[stack[i-1]^1];
    			}
    			Last=i;
    		}
    	}
    }
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n=read(0),m=read(0);
    	for (int i=1;i<=m;i++){
    		int x=read(0),y=read(0);
    		D[x]++,D[y]++;
    		insert(x,y);
    	}
    	for (int i=1;i<=n;i++)	if (D[i]&1)	insert(0,i);
    	for (int i=0;i<=n;i++)	Cur[i]=now[i];
    	for (int i=0;i<=n;i++){
    		top=0,Dfs(i,0);
    		solve();
    	}
    	printf("%d
    ",Cnt);
    	for (int i=1;i<=Cnt;i++)
    		printf("%d %d
    ",Ans[i][0],Ans[i][1]);
    	return 0;
    }
    
    作者:Wolfycz
    本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
  • 相关阅读:
    QT:不规则窗口的实现
    Sql Server (错误:7302)
    Qt源码分析之信号和槽机制
    Linux下如何发布Qt程序
    QT程序制作deb包并安装在应用程序菜单
    Another Look at Events(再谈Events)
    Qt全局热键(windows篇)(使用RegisterHotKey和句柄进行注册)
    新浪微博回归平静
    Qt中 QString 和int, char等的“相互”转换,关键是QString.toLocal8Bit().data();
    QT中异形窗口的绘制(winEvent处理WM_NCHITTEST消息)
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/14986452.html
Copyright © 2011-2022 走看看