hdu 6178 Monkeys dfs匹配

来源:互联网 发布:java microservice 编辑:程序博客网 时间:2024/05/16 19:50

题意:在一个树上,把n个猴子放到k个位置,求最小的边数;
思路:求二分匹配最小顶点覆盖。范围较大,可以dfs从叶子节点往根节点选(贪心)。
由于读入很大,普通挂也T, 必须用fread

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#define scan(n) FastIO::read(n)using namespace std;namespace FastIO {    const int SIZE = 1 << 16;    char buf[SIZE], obuf[SIZE], str[60];    int bi = SIZE, bn = SIZE, opt;    int read(char *s) {        while (bn) {            for (; bi < bn && buf[bi] <= ' '; bi++);            if (bi < bn) break;            bn = fread(buf, 1, SIZE, stdin);            bi = 0;        }        int sn = 0;        while (bn) {            for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];            if (bi < bn) break;            bn = fread(buf, 1, SIZE, stdin);            bi = 0;        }        s[sn] = 0;        return sn;    }    bool read(int& x) {        int n = read(str), bf;        if (!n) return 0;        int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;        for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';        if (bf < 0) x = -x;        return 1;    }};const int MAXN=200005;int head[MAXN];int sum,cnt;struct node{    int to, from;}G[MAXN];void add(int u, int v){    G[cnt].to=v;    G[cnt].from=head[u];    head[u]=cnt++;}int dfs(int u, int fa){    int flag=0;//若为叶子节点,则回溯后,sum+=1;    for(int i=head[u];~i;i=G[i].from)    {        int v=G[i].to;        if(v==fa)            continue;        if(!dfs(v, u)) flag=1;    }    sum+=flag;    return flag;}int main(){    int n, k;    int t;    scan(t);    while(t--)    {        scan(n);        scan(k);        int x;        memset(head, -1, sizeof(head));        cnt=0;        for(int i=1;i<n;++i)        {            scan(x);            add(i+1, x);            add(x,i+1);        }        sum=0;        dfs(1, 0);        int ans;        if(k<=sum*2)            ans=(k+1)/2;        else            ans=k-sum;        cout<<ans<<endl;    }    return 0;}

自己之前一直wrong的代码,终于对了。

#include <bits/stdc++.h>using namespace std;const int MAXN=100005;namespace IN{const int inBufferSize = 1<<25;char inBuffer[inBufferSize];char *inHead = NULL, *inTail = NULL;inline char Getchar(){    if(inHead == inTail)        inTail=(inHead=inBuffer)+fread(inBuffer, 1, inBufferSize, stdin);    return *inHead++;}}#define getchar() IN::Getchar()template <typename T>inline void scan_ud(T &ret){    char c = getchar();    ret = 0;    while (c < '0' || c > '9') c = getchar();    while (c >= '0' && c <= '9')        ret = ret * 10 + (c - '0'), c = getchar();}bool vis[MAXN];vector <int> G[MAXN];int m, ans;void dfs(int x, int pre){    for(int i=0; i<G[x].size(); ++i)    {        if(!vis[G[x][i]]&&G[x][i]!=pre)        dfs(G[x][i], x);    }    if(m==0||m==1)        return;    if(!vis[pre]&&!vis[x])    {        vis[pre]=vis[x]=true;        ans++;        m-=2;        return ;    }}int main(){    int t;    scanf("%d", &t);    while(t--)    {        int n;        scan_ud(n);        scan_ud(m);        int x;        ans=0;        memset(vis, false, sizeof(vis));        //memset(use, false, sizeof(use));        for(int i=1; i<=n; ++i)            G[i].clear();        for(int i=1; i<=n-1; ++i)        {            scan_ud(x);            G[x].push_back(i+1);            G[i+1].push_back(x);        }//        for(int i=1;i<=n;++i)//            printf("%d\n", G[i].size());        vis[0]=true;        dfs(n, 0);        printf("%d\n", ans+m);    }    return 0;}