zoukankan      html  css  js  c++  java
  • agc025E

    题目大意

    题解

    一开始想dp,然后想不出来直接大力猜结论+胡乱构造

    显然答案上界是Σmin(2,边i覆盖次数),手玩样例发现可以构出来且举不出反例

    考虑构造,显然需要决策的只有覆盖次数>=2的边,则每次把经过这类边剩余路径最少的那条拿出来,随便找一条经过其的路径定向并更新,这样一定可以构出来,然后发现现在并不会证了

    题解做法:每次找叶子,把经过其父亲边的链(u,a)和(u,b)找出,将其变成(u,a)和(a,b),然后(u,b)的方向取决于(a,b)的方向,这样就可以不断往上删了

    关于上面的奇妙做法,在值相同时把编号随机赋权交了3次都过了,所以应该是对的

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define pd(x,y) (bg[x]<=bg[y] && ed[y]<=ed[x])
    #define ll long long
    //#define file
    using namespace std;
    
    int rd[2001];
    struct type{int s,x;} s;
    bool operator < (type a,type b) {return !(a.s<b.s || a.s==b.s && rd[a.x]<rd[b.x]);}
    priority_queue<type> hp;
    int n,m,i,j,k,l;
    int a[4001][2],ls[2001],len,fa[2001],d[2001];
    int b[2001][2],bg[2001],ed[2001];
    int ans[2001],bz[2001],Ans,sum[2001];
    vector<int> c[2001];
    
    void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}
    void swap(int &x,int &y) {int z=x;x=y;y=z;}
    void dfs(int Fa,int t)
    {
    	int i;
    	fa[t]=Fa,d[t]=d[Fa]+1,bg[t]=++j;
    	for (i=ls[t]; i; i=a[i][1])
    	if (a[i][0]!=Fa)
    	dfs(t,a[i][0]);
    	ed[t]=j;
    }
    void add(int x,int y,int s)
    {
    	while (!pd(x,y)) c[x].push_back(s),++sum[x],x=fa[x];
    	while (x!=y) c[y].push_back(s),++sum[y],y=fa[y];
    }
    void change(int x,int y,int s)
    {
    	while (!pd(x,y)) {--sum[x];if (sum[x]>0) hp.push(type{sum[x],x}); bz[x]|=s;x=fa[x];}
    	while (x!=y) {--sum[y];if (sum[y]>0) hp.push(type{sum[y],y}); bz[y]|=3-s;y=fa[y];}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("agc025E.in","r",stdin);
    	#endif
    	
    	srand(time(NULL));
    	scanf("%d%d",&n,&m);
    	fo(i,1,n) rd[i]=i;
    	random_shuffle(rd+1,rd+n+1);
    	fo(i,1,n-1) scanf("%d%d",&j,&k),New(j,k),New(k,j);
    	j=0,dfs(0,1);
    	fo(i,1,m) {scanf("%d%d",&b[i][0],&b[i][1]);if (b[i][0]>b[i][1]) swap(b[i][0],b[i][1]);add(b[i][0],b[i][1],i);}
    	fo(i,2,n)
    	{
    		l=sum[i];
    		Ans+=(l>0)+(l>1);
    		if (l>1) hp.push(type{l,i});
    	}
    	
    	while (!hp.empty())
    	{
    		s=hp.top();hp.pop();
    		if (bz[s.x]==3) continue;
    		if (!bz[s.x] || bz[s.x]==2) l=1;
    		else l=2;
    		bz[s.x]|=l;
    		
    		do{
    			k=c[s.x].back(),c[s.x].pop_back();
    		} while (ans[k]);
    		if (pd(s.x,b[k][0])) ans[k]=l;
    		else ans[k]=3-l;
    		change(b[k][0],b[k][1],ans[k]);
    	}
    	
    	printf("%d
    ",Ans);
    	fo(i,1,m)
    	if (ans[i]==1)
    	printf("%d %d
    ",b[i][0],b[i][1]);
    	else
    	printf("%d %d
    ",b[i][1],b[i][0]);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Kinect研究文档
    Unity使用Win10语音
    使用unity2017.3 vuforia7摄像头放大的问题
    Unity响应Android的返回键,退出当前Activity
    unity调用Android百度地图
    Unity带参数的协程
    Android jenkins动态参数配置
    如何下载浏览器视频
    mac 如果修改环境变量
    mac如何修改hosts文件
  • 原文地址:https://www.cnblogs.com/gmh77/p/14040250.html
Copyright © 2011-2022 走看看