• 51nod1757 大灾变


    能想到二分答案+最大流判断是否符合。但是不知道如何建图qaq。参考的是http://blog.csdn.net/fsss_7/article/details/52132046的建图方法

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define clr(x,c) memset(x,c,sizeof(x))
    #define qwq(x) for(edge *o=head[x];o;o=o->next)
    int read(){
    	int x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return x;
    }
    const int nmax=2e3+5;
    const int maxn=2e5+5;
    const int inf=0x7f7f7f7f;
    struct edge{
    	int to,cap;edge *next,*rev;
    };
    edge es[maxn<<3],*pt=es,*head[maxn];
    void add(int u,int v,int d){
    	pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
    	pt->to=u;pt->cap=0;pt->next=head[v];head[v]=pt++;
    	head[u]->rev=head[v];head[v]->rev=head[u];
    }
    
    vector<int>a[nmax];
    int dis[50][nmax],in[nmax],on[nmax];
    void dfs(int p,int x,int fa){
    	int u;
    	rep(i,0,a[x].size()-1) if((u=a[x][i])!=fa)
    	  dis[p][u]=dis[p][x]+1,dfs(p,u,x);
    }
    
    edge *cur[maxn],*p[maxn];
    int cnt[maxn],h[maxn];
    int maxflow(int s,int t,int n){
    	clr(cnt,0);cnt[0]=n;clr(h,0);
    	int flow=0,a=inf,x=s;edge *e;
    	while(h[s]<n){
    		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[x]==h[e->to]+1) break;
    		if(e){
    			a=min(a,e->cap);cur[x]=p[e->to]=e;x=e->to;
    			if(x==t){
    				while(x!=s) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to;
    				flow+=a;a=inf;
    			}
    		}else{
    			if(!--cnt[h[x]]) break;
    			h[x]=n;
    			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e;
    			cnt[h[x]]++;
    			if(x!=s) x=p[x]->rev->to;
    		}
    	}
    	return flow;
    }
    
    int check(int x,int n,int m){
    	int s=0,t=n+m*x+1;
    	pt=es;clr(head,0);
    	rep(i,1,n) if(!in[i]) add(s,i,1);
    	rep(i,1,m) {
    		rep(j,1,x) add(n+(i-1)*x+j,t,1);
    		rep(j,1,x-1) add(n+(i-1)*x+j,n+(i-1)*x+j+1,inf);
    	}
    	rep(i,1,m){
    		rep(j,1,n) if(!in[j]&&dis[i][j]<=x) add(j,n+(i-1)*x+dis[i][j],1);
    	}
    	return maxflow(s,t,t+1);
    }
    int main(){
    	int n=read(),m=read(),u,v;
    	rep(i,1,n-1) u=read(),v=read(),a[u].push_back(v),a[v].push_back(u);
    	rep(i,1,m) u=read(),in[u]=1,on[i]=u;
    	rep(i,1,m) dfs(i,on[i],0);
    	int l=0,r=n,mid,ans=0;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(check(mid,n,m)==n-m) ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

    基准时间限制:3 秒 空间限制:262144 KB 分值: 160 难度:6级算法题
     收藏
     关注
    死亡之翼降临了!艾泽拉斯大陆的子民们必须逃出他的魔爪!
    艾泽拉斯的结构是一棵树,这棵树上的一些节点是地精建造的通往地下避难所的洞口。
    除了这些洞口之外,树上的每个节点上都有一个种族,每个种族通过树上的一条边都需要一个单位时间。
    因为地精比较矮小,所以洞口很窄,每个单位时间只能让一个种族通过,但是一个单位时间内的一个节点上可以存在多个种族。
    地精们需要你求出最少需要多少单位时间才能让所有种族躲进地下避难所。
    【注意题目有修改,洞口不一定是叶子节点】
    Input
    第1行两个整数n(n<=2000)和m(m<=40)表示节点个数和洞口个数
    接下来n-1行每行两个整数表示树上的每一条边
    第n+1行m个整数表示所有洞口的编号,保证洞口是叶子节点
    Output
    一个整数t表示让所有种族躲进地下避难所的最少时间
    Input示例
    6 2
    1 2
    1 3
    1 4
    1 5
    5 6
    3 6
    Output示例
    3
  • 相关阅读:
    【bzoj2006】超级钢琴
    【bzoj4940】这是我自己的发明
    【arc076E】Connected?
    【agc004C】AND Grid
    选举
    几何
    打击目标
    【CF Gym100228】Graph of Inversions
    【CodeChef】Chef and Graph Queries
    大包子玩游戏
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5862723.html
Copyright © 2020-2023  润新知