2012-2013 ACM-ICPC, NEERC, Central Subregional Contest J Computer Network1

题意:求一条边使得加入这条边以后的消除的桥尽量多。

在同一个边双连通分量内加边肯定不会消除桥的,

求边双连通分量以后缩点,把桥当成边,实际上是要选一条最长的链。

缩点以后会形成一颗树,一定不存在环否则和桥的定义矛盾,求树上的最远点对。

树上的最远点对用dpT了,实际上两次dfs就行了,第一次随便选一个点dfs找到最远的点,

再从那个点dfs找最远的点就是树上的最远点对,为什么这样是对的呢?反向来构造,假设已经找了最长的链,

往链上某点上添加一条链,这条链的长度一定小于这个点到两个端点之中距离的最小的那个,

因此无论从哪个点出发dfs,一定会到达最长的链的一个端点。第二遍就一定能找到最长的链。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5, maxm = 2e5+5;
int head[maxn],nxt[maxm],to[maxm],ecnt;

void addEdge(int u,int v)
{
    to[ecnt] = v;
    nxt[ecnt] = head[u];
    head[u] = ecnt++;
}

int pre[maxn],low[maxn],dfs_clock;
bool cut[maxm];

void tarjan(int u,int fa)
{
    pre[u] = low[u] = ++dfs_clock;
    for(int i = head[u]; ~i; i = nxt[i]){
        int v = to[i];
        if(!pre[v]){
            tarjan(v,i);
            low[u] = min(low[u],low[v]);
            if(low[v] > pre[u]){
                //if(fa<0) cut[i] = cut[i^1] = ~nxt[head[u]];
                //else
                cut[i] = cut[i^1] = true;
            }
        }else if( (i^1)!=fa && pre[v] < pre[u]){
            low[u] = min(pre[v],low[u]);
        }
    }
}

int eccno[maxn],ecc_cnt;
int pid[maxn];
void dfs(int u)
{
    eccno[u] = ecc_cnt;
    for(int i = head[u]; ~i; i = nxt[i] ) if(!cut[i]){
        if(!eccno[to[i]]) dfs(to[i]);
    }
}

vector<int> G[maxn];
#define PB push_back
int deg[maxn];

void find_ecc(int n)
{
    dfs_clock = 0;
    tarjan(0,-1);
    ecc_cnt = 0;
    for(int i = 0; i < n; i++){
        if(!eccno[i]){
            ecc_cnt++;
            pid[ecc_cnt] = i;
            dfs(i);
        }
    }

    for(int i = 1; i <= ecc_cnt; i++) G[i].clear();
    memset(deg,0,sizeof(deg));
    for(int i = 0; i < ecnt; i+=2){
        if(cut[i]){
            int u = eccno[to[i]], v = eccno[to[i^1]];
            G[u].PB(v); G[v].PB(u);
            deg[u]++; deg[v]++;
        }
    }
}

void init()
{
    memset(head,-1,sizeof(head));
    ecnt = 0;
}

int MaxD,poi;

void dfs(int u,int fa,int d)
{
    if(d > MaxD){
        MaxD = d;
        poi = u;
    }
    for(int i = 0; i <(int)G[u].size(); i++){
        int v = G[u][i]; if(v == fa) continue;
        dfs(v,u,d+1);
    }
}

void solve()
{
    MaxD = 0; poi = 1;
    dfs(1,-1,0);
    int u = poi;
    MaxD = 0; poi = u;
    dfs(u,-1,0);
    int v = poi;
    printf("%d %d\n",pid[u]+1,pid[v]+1);
}

int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    int n,m;scanf("%d%d",&n,&m);
    init();
    for(int i = 0; i < m; i++){
        int u,v; scanf("%d%d",&u,&v); u--;v--;
        addEdge(u,v); addEdge(v,u);
    }
    find_ecc(n);
    solve();
    return 0;
}
时间: 2024-10-11 15:26:32

2012-2013 ACM-ICPC, NEERC, Central Subregional Contest J Computer Network1的相关文章

2018-2019 ICPC, NEERC, Southern Subregional Contest

目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Cloud Computing(线段树) D.Garbage Disposal(模拟) E.Getting Deals Done(二分) F.Debate(贪心) H.BerOS File Suggestion(后缀自动机) I.Privatization of Roads in Berland(网络流)

ACM ICPC 2011–2012, NEERC, Northern Subregional Contest J. John’s Inversions(合并排序求逆序数对数)

题目链接:http://codeforces.com/gym/100609/attachments 题目大意:有n张牌,每张牌有红色和蓝色两面,两面分别写了一些数字,同种颜色的任意两个数字若排在前面的数字比排在后面的数字大就叫做一对逆序数.求怎样排序得到的逆序数对最少. 解题思路:其中一种颜色的数字是顺序且这种颜色数字相同时对应的另一种颜色的数字是顺序时得到的逆序数对数最少.难点在于求逆序数对数.因为数量很大O(n^2)复杂度不能满足,这里根据合并排序的原理求解每个数字前面有多少个比它大的数字,

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) 体验记

原文链接https://www.cnblogs.com/zhouzhendong/p/CF1070.html 比赛网址:http://codeforces.com/contest/1070 感受 本来只打算玩玩的. 结果玩的海星. 我做 A 题的时候可能比较浮躁吧,各种傻错误,爆了 7 个罚时. 我 A 还没过,cly 神仙已经把 CDK 切光了. 4点半过一会儿,各自回家.cly 要剃头,就咕咕咕了.我本来也要剃的,后来临时决定先打题. 然后过了 A ,顺手切掉了 H 和 F ,开了 E ,猜

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution

从这里开始 题目列表 瞎扯 Problem A Find a Number Problem B Berkomnadzor Problem C Cloud Computing Problem D Garbage Disposal Problem E Getting Deals Done Problem F Debate Problem G Monsters and Potions Problem H BerOS File Suggestion Problem I Privatization of

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

http://codeforces.com/contest/1070 A 给你一个d和s,求一个最小的数,使的能整除d,并且每位数的和为s. 如果确定了某n位数取模d的值,那么再计算同样的n位数,取模d也是相同的值时,就多此一举了.比如10%2 == 0  20%2 == 0  同样是两位数,取模2都是等于0.所以取最小的就可以了. 1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) Solution

A. Find a Number Solved By 2017212212083 题意:$找一个最小的n使得n % d == 0 并且 n 的每一位数字加起来之和为s$ 思路: 定义一个二元组$<d, s>$ 表示当前状态模d的值,以及每一位加起来的值 跑最短路,从$<0, 0>  跑到 <0, s>$ 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 +

hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 735    Accepted Submission(s): 305 Problem Description Bob has N balls and A b

hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup

http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Alice was felling into a cave. She found a strange door with a number square m

2013 ACM/ICPC Asia Regional Chengdu Online

题目链接: 2013 ACM/ICPC Asia Regional Chengdu Online 上年网选被虐得好惨,遂决定把题目拿回来搞一遍, 不会的题补之! A. 2013 ACM/ICPC Asia Regional Chengdu Online,布布扣,bubuko.com