2017多校第10场第8题(树上边匹配)

来源:互联网 发布:画图软件有哪些 编辑:程序博客网 时间:2024/06/06 04:02

一开始想到了二分图匹配,找出最大匹配以后如果还有猴子剩下,答案就是匹配数加剩下的猴子数。

后来写完就觉得匈牙利复杂度不够,瞎交了一发 tle了

后来知道了dfs的暴力匹配,创建一个0点,和1 相连,然后跑dfs,见到一条边,两个点都没有被选的话就选。

dfs以后如果0被选了 匹配数就减1,然后算答案

#include<cstdio>#include<vector>#include<cstring>using namespace std;const int maxn = 100000+10;int n,k,a;vector<int>G[maxn];int vis[maxn];int in[maxn];int used[maxn];int ans ;namespace fastIO {    #define BUF_SIZE 100000    //fread -> read    bool IOerror = 0;    inline char nc() {        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;        if(p1 == pend) {            p1 = buf;            pend = buf + fread(buf, 1, BUF_SIZE, stdin);            if(pend == p1) {                IOerror = 1;                return -1;            }        }        return *p1++;    }    inline bool blank(char ch) {        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';    }    inline void read(int &x) {        char ch;        while(blank(ch = nc()));        if(IOerror)            return;        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');    }    #undef BUF_SIZE};using namespace fastIO;void dfs(int u,int fa){    int len = G[u].size();    for(int i=0;i<len;i++)    {        int v = G[u][i];        dfs(v,u);    }    if(!vis[u]&&!vis[fa])    {        ans ++; vis[u] = 1; vis[fa] = 1;    }}int main(){    int cases;    read(cases);    while(cases--)    {        read(n); read(k);        for(int i=0;i<=n;i++) G[i].clear(); ans = 0;        for(int i=2;i<=n;i++)        {            read(a);            G[a].push_back(i);        }        G[0].push_back(1);        memset(vis,0,sizeof(vis));        dfs(1,-1);        if(vis[0]) ans--;        if(ans*2>=k) printf("%d\n",(k+1)/2);        else  printf("%d\n",ans+(k-2*ans));    }    return 0;}//7 7//1 2 6 6 2 4