zoukankan      html  css  js  c++  java
  • [LibreOJ β Round #3] 绯色 IOI(抵达)

    一、题目

    点此看题

    二、解法

    首先考虑任意两个不同的城市庇护所不同意味着什么。我首先想出来一个 ( t naive) 的结论:每个叶子的庇护所一定是它的父亲,所以有解的条件是每个非叶节点至多连接一个叶子。

    要让结论升级才能做题,我们考虑叶节点父亲的庇护所一定是他自己,那么这两个节点的匹配方案是唯一确定的,我们把这两个节点同时删去之后得到一个新树,递归操作直到树为空即可,所以如果有解匹配方案也只有一种。

    这种匹配方案是好求的,我们用队列模拟一下删叶子的过程即可。这个唯一的匹配方案就可以把原限制转化成若干个偏序关系,我们把偏序关系建成拓扑图,依次考虑权值 (1 ightarrow n) 赋值,维护一个关于编号的小根堆,每次把堆顶删去即可。

    三、总结

    观察性质,可以从一些简单结论入手,然后再考虑上升结论。

    树的匹配问题可以从叶子着手考虑,因为叶子处的匹配可能最简单。

    #include <cstdio>
    #include <vector>
    #include <queue>
    using namespace std;
    const int M = 500005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,cnt,a[M],d[M],ans[M];vector<int> g1[M],g2[M];
    void link(int u,int v)
    {
    	if(u==v) return ;
    	g2[u].push_back(v);d[v]++;
    }
    void tpsort()
    {
    	priority_queue<int,vector<int>,greater<int> >q;
    	for(int i=1;i<=n;i++)
    		if(d[i]==0) q.push(i);
    	while(!q.empty())
    	{
    		int u=q.top();q.pop();
    		ans[++m]=u;
    		for(int i=0;i<g2[u].size();i++)
    		{
    			int v=g2[u][i];
    			d[v]--;
    			if(d[v]==0) q.push(v);
    		}
    	}
    	if(m!=n) {puts("-1");return ;}
    	for(int i=1;i<=n;i++)
    		printf("%d ",ans[i]);
    }
    signed main()
    {
    	n=read();
    	for(int i=1;i<n;i++)
    	{
    		int u=read(),v=read();
    		g1[u].push_back(v);
    		g1[v].push_back(u);
    		a[u]++;a[v]++;
    	}
    	queue<int> q;
    	for(int i=1;i<=n;i++)
    		if(a[i]==1) q.push(i);
    	while(!q.empty())
    	{
    		int u=q.front(),t=0;q.pop();
    		for(int i=0;i<g1[u].size();i++)
    			if(a[g1[u][i]]>0)//his shelter
    				t=g1[u][i],a[g1[u][i]]=0;
    		if(!t) continue;
    		//build some edge
    		for(int i=0;i<g1[u].size();i++)
    			link(t,g1[u][i]);
    		for(int i=0;i<g1[t].size();i++)
    			link(u,g1[t][i]);
    		//update the degree
    		for(int i=0;i<g1[t].size();i++)
    		{
    			a[g1[t][i]]--;
    			if(a[g1[t][i]]==1) q.push(g1[t][i]);
    		}
    		cnt++;
    	}
    	if(cnt<n/2 || n%2) {puts("-1");return 0;}
    	tpsort();
    }
    
  • 相关阅读:
    Scoket简介
    AOP
    Windows服务
    Nginx 教程 (1):基本概念
    异步编程
    并发编程
    常用排序
    序列化
    MSBuild/Projectjson
    不汇报是职场发展的绊脚石
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15018539.html
Copyright © 2011-2022 走看看