Codeforces 848C

原题链接: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;
}


猜你喜欢

转载自blog.csdn.net/u012602144/article/details/78044389