Codeforces 848C

来源:互联网 发布:caffe deploy.proto 编辑:程序博客网 时间:2024/06/05 20:50

原题链接:http://codeforces.com/problemset/problem/848/C

大致题意:给出n个点,m条边的图,每次删去有公共点的2条边,问最多删几次,及其中一种方案。

先简化一下题意,如果给出的是一颗树,对于某一个节点,如果它向下有2*k条边,则可以直接把这2*k条边两两配对删去;如果有2*k+1条边,则将剩下的一条边和连向这个节点的父亲的边配对删去,如果是根节点则直接放弃。显然,这样的执行方案是最优的,可以配对删去(n-1) div 2 次。

然后如果当前节点有一些既不是儿子边也不是父亲边的边,则可以当做连向其儿子节点的边处理,因为这种边和它的儿子边一样符合配对的要求,所以可以直接当做儿子边处理。

代码:

#include <bits/stdc++.h>using namespace std;inline void read(int &x){    char ch;    bool flag=false;    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());    x=flag?-x:x;}inline void read(long long &x){    char ch;    bool flag=false;    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());    x=flag?-x:x;}inline void write(int x){    static const int maxlen=100;    static char s[maxlen];        if (x<0) {   putchar('-'); x=-x;}    if(!x){ putchar('0'); return; }    int len=0; for(;x;x/=10) s[len++]=x % 10+'0';    for(int i=len-1;i>=0;--i) putchar(s[i]);}const int MAXN = 310000;const int MAXM = 610000;int n,m;int pre[ MAXM ],now [ MAXN ], ed [ MAXM ] , tot;int st[ MAXM ];bool use[ MAXM ];void build(int a,int b){pre[++tot]=now[a];now[a]=tot;ed[tot]=b;st[tot]=a;}map<int,int> M;int dfs(int x,int fa){int last=0;for (int p=now[x];p;p=pre[p])    if ( !use[ p/2 ] )        {            use[ p/2 ]=1;            int tmp=0;            tmp=dfs( ed[p] , x );            if (tmp!=0)                {                    M[tmp]=p;                }            else                if (last)                    {                        M[last]=p^1;                        last=0;                    }                else                    last=p;        }return last;}int main(){    read(n); read(m);    tot=1;    for (int i=1;i<=m;i++)        {            int a,b;            read(a); read(b);            build(a,b);            build(b,a);        }    for (int i=1;i<=n;i++)        dfs(i,0);    printf("%d\n",M.size());    for ( auto S:M)        printf("%d %d %d\n",ed[ S.first ] , st[ S.first ] , st[ S.second ]);    return 0;}


原创粉丝点击