BUPT Summer Journey #test6 D

 

D. 爱好和平 2014新生暑假个人排位赛06

时间限制 1000 ms     内存限制65536 KB    

题目描述

在星际时代,每个帝国都靠着贸易路线连接着各个联盟星球,这些贸易路线都是双向可达的。一个帝国的综合实力由他贸易连接着的联盟星球数决定。
学姐作为Mays帝国的领袖,长期与Luke帝国保持着敌对关系,爱好和平的学姐希望结束长达几个世纪的战争,于是找实验室定做了一颗代号小苹果的炸弹,可以定点摧毁一颗星球,这颗星球被毁后,与它相连的全部贸易就都被切断了,这样Luke帝国可能就被切断为一个小联盟,他们就再也不会对学姐的地位构成威胁啦~
经过调查,Luke帝国为了节约经费,他的联盟星之间都有且仅有一条直接或间接的贸易通路。
现在给出Luke帝国的贸易线路,学姐想知道摧毁哪一颗行星可以使得分裂后的若干Luke联盟威胁最大的分部最小。

输入格式

输入有多组数据,组数不大于10组。每一组开头一行为n,m,表示Luke帝国的联盟星球数量,和贸易关系数,接下来m行,每行两个整数u,v,表示星球u,v之间存在直接的贸易路线,1<=u,v<=n,1<=n,m<=100000

输出格式

输出一个数表示推荐学姐摧毁的星球,如果有多解,输出编号最小的一个。

输入样例

5 4
1 2
1 3
1 4
4 5

输出样例

1

 

思路:因为经过调查,Luke帝国为了节约经费,他的联盟星之间都有且仅有一条直接或间接的贸易通路。所以可以看成一个树。对于树中的每个节点,记录下它子节点的连通块中节点个数,然后往上的时候就累加,则父节点联通块个数就是总数减子节点联通块个数的总和。然后一遍dfs即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define maxn 100005
//#define LOCAL
using namespace std;
vector<int> G[maxn];
int sv[maxn],fv[maxn],vis[maxn],connected[maxn];
int n,m,deep;
template<class T>
inline bool read(T &n)
{
    T signal = 1,x =0;
    char ch =getchar();
    while((ch < '0' || ch >'9') && ch != EOF && ch != '-')
        ch = getchar();
    if(ch == EOF) return false;
    if(ch == '-') ch = getchar(),signal = -1;
    while(ch>='0' && ch <= '9'){
        x *= 10;
        x += ch -'0';
        ch = getchar();
    }
    n = signal * x;
    return true;
}
void dfs(int u,int f)
{
    vis[u]=1;
    //printf("u=%d f=%d\n",u,f);system("pause");
    int cnt=0;
    connected[u]=1;
    for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(v!=f&&!vis[v])
            {

                cnt++;
                dfs(v,u);//if(u==4)printf("connect[%d]=%d\n",v,connected[v]);
                sv[u]=max(sv[u],connected[v]);
                connected[u]+=connected[v];
            }

        }
    if(cnt==0){sv[u]=0;connected[u]=1;}
    //cout<<cnt<<endl;
    //value1[u]=n-1;

}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    while(scanf("%d%d",&n,&m)==2)
    {
        //cout<<n<<' '<<m<<endl;
        for(int i=1;i<=n;i++)G[i].clear();
        memset(sv,0,sizeof(sv));
        memset(fv,0,sizeof(fv));
        //memset(connected,0,sizeof(connected));
        for(int i=1;i<=m;i++)
        {
            int a,b;
            read(a);read(b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        memset(vis,0,sizeof(vis));
        dfs(1,-1);
        //memset(vis,0,sizeof(vis));
        //for(int i=1;i<=n;i++)printf("value[%d]=%d\n",i,sv[i]);
        //dfs2(1,-1);
        //cout<<value[1]<<endl;
        //for(int i=1;i<=n;i++)printf("value[%d]=%d\n",i,fv[i]);
        //for(int i=1;i<=n;i++)printf("value[%d]=%d\n",i,max(n-connected[i],sv[i]));
        int ans=0x7fffffff,maxx;
        for(int i=1;i<=n;i++)if(max(n-connected[i],sv[i])<ans){ans=max(n-connected[i],sv[i]);maxx=i;}
        printf("%d\n",maxx);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值