zoukankan      html  css  js  c++  java
  • hdu 5452(树链刨分)

    看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西。。。

    Minimum Cut

    Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
    Total Submission(s): 453    Accepted Submission(s): 180


    Problem Description
    Given a simple unweighted graph G (an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let T be a spanning tree of G.
    We say that a cut in G respects T if it cuts just one edges of T.

    Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T.
     
    Input
    The input contains several test cases.
    The first line of the input is a single integer t (1t5) which is the number of test cases.
    Then t test cases follow.

    Each test case contains several lines.
    The first line contains two integers n (2n20000) and m (n1m200000).
    The following n1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
    Next mn+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T.
     
    Output
    For each test case, you should output the minimum cut of graph G respecting the given spanning tree T.
     
    Sample Input
    1 4 5 1 2 2 3 3 4 1 3 1 4
     
    Sample Output
    Case #1: 2
     
    Source
     
     
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    #define N 20020
    
    int n,m;
    struct node
    {
    	int to,next;
    }edge[2*N];
    
    int pre[N],cnt;
    int siz[N],son[N],top[N],dep[N],fa[N],w[N];
    int index;
    int cnt1[N];
    
    void add_edge(int u,int v)
    {
    	edge[cnt].to=v;
    	edge[cnt].next=pre[u];
    	pre[u]=cnt++;
    }
    
    void dfs(int s,int deep,int father)
    {
    	dep[s]=deep;
    	siz[s]=1;
    	fa[s]=father;
    	int mx=-1;
    	son[s]=0;
    	for(int p=pre[s];p!=-1;p=edge[p].next)
    	{
    		int v=edge[p].to;
    		if(v==father) continue;
    		dfs(v,deep+1,s);
    		if(siz[v]>mx)
    		{
    			mx=siz[v];
    			son[s]=v;
    		}
    		siz[s]+=siz[v];
    	}
    }
    
    void dfs1(int s,int father)
    {
    	if(son[s]!=0)
    	{
    		w[ son[s] ]=++index;
    		top[ son[s] ]=top[s];
    		dfs1(son[s],s);
    	}
    	for(int p=pre[s];p!=-1;p=edge[p].next)
    	{
    		int v=edge[p].to;
    		if(v==father||v==son[s]) continue;
    		w[v]=++index;
    		top[v]=v;
    		dfs1(v,s);
    	}
    }
    
    
    
    int Scan()     //输入外挂
    {
    	  int res=0,ch,flag=0;
    	  if((ch=getchar())=='-')
    		  flag=1;
    	  else if(ch>='0'&&ch<='9')
    		  res=ch-'0';
    	  while((ch=getchar())>='0'&&ch<='9')
    			res=res*10+ch-'0';
    	  return flag?-res:res;
     }
    
    
    void Out(int a)//输出外挂
    {
    	if(a>9)
    		Out(a/10);
    	putchar(a%10+'0');
    }
    
    int in()
    {
        int flag = 1;
        char ch;
        int a = 0;
        while((ch = getchar()) == ' ' || ch == '
    ');
        if(ch == '-') flag = -1;
        else
        a += ch - '0';
        while((ch = getchar()) != ' ' && ch != '
    ')
        {
            a *= 10;
            a += ch - '0';
        }
        return flag * a;
    }
    
    //你卡这个复杂度真的好吗,不过也怪自己学的少。
    
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	int tt=1;
    	while(T--)
    	{
    		memset(pre,-1,sizeof(pre));
    		cnt=0;
    		scanf("%d%d",&n,&m);
    		for(int i=0;i<n-1;i++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			add_edge(x,y);
    			add_edge(y,x);
    		}
    		//然后就是进行树链刨分
    		dfs(1,1,1);
    		top[1]=1;
    		index=0;
    		w[1]=0;
    		dfs1(1,-1);
    
    		memset(cnt1,0,sizeof(cnt1));
    
     		for(int i=n-1;i<m;i++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    
    			while(top[x]!=top[y])
    			{
    				if( top[x] > top[y] )
    				{
    					cnt1[w[top[x]] ]++;
    					cnt1[w[x]+1]--;
    					x = fa[ top[x] ];
    				}
    				else
    				{
    					cnt1[ w[ top[y] ] ]++;
    					cnt1[ w[y]+1 ]--;
    					y = fa[ top[y] ];
    				}
    			}
    			if(dep[x] < dep[y])
    			{
    				cnt1[ w[son[x] ] ]++;
    				cnt1[ w[y]+1 ]--;
    			}
    			else if(dep[x] >dep[y] )
    			{
    				cnt1[w[son[y]] ]++;
    				cnt1[w[x]+1 ]--;
    			}
    
    		}
    
    		int ans=10000000;
    		for(int i=1;i<=index;i++)
    		{
    			cnt1[i]+=cnt1[i-1];
    			ans=min(ans,cnt1[i]);
    		}
    		printf("Case #%d: ",tt++);
    		printf("%d
    ",ans+1);
    	}
        return 0;
    }
    

      

  • 相关阅读:
    C#listbox使用方法
    poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 黑白无常
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/4823885.html
Copyright © 2011-2022 走看看