zoukankan      html  css  js  c++  java
  • codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

    J. Computer Network

    Time Limit: 1 Sec  

    Memory Limit: 256 MB

    题目连接

    http://codeforces.com/gym/100114

    Description

    The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relaying information from server to server. Current network setup enables communication for any pair of servers. The network administrator strives to maximize network reliability. Some communication links in the network were identified as critical. A failure on any critical link will split the network into disconnected segments. Company management responded to the administrator’s concerns and agreed to fund another communication link, provided that when the new link goes online the number of critical links will be minimized. Write a program that, given a network configuration, will pick a pair of servers to be connected by the new communication link. If several such pairs allow minimizing the number of critical links then any of them will be considered as a correct answer. Example. The following figure presents a network consisting of 7 servers and 7 communication links. Essential links are shown as bold lines. A new link connecting servers #1 and #7 (dotted line) can reduce the number of the critical links to only one

    Input

    The first line contains two space-delimited integer numbers n (the number of servers) and m (the number of communication links). The following m lines describe the communication links. Each line contains two space-delimited integers xi and yi, which define the IDs of servers connected by link number i. Servers are identified with natural numbers ranging from 1 to n.

    Output

    The output file should contain a single line with space-delimited integers x and y, the IDs of servers to be connected by the new link..

    Sample Input

    7 7 1 2 2 3 2 4 2 6 3 4 4 5 6 7

    Sample Output

    1 7

    HINT

    1 ≤ n ≤ 10 000; 1≤ m ≤ 100 000; 1 ≤ xi, yi ≤ n; xi ≠ yi.

    题意

    给你一个图,让你连一条边之后,使得这个图的桥最少

    题解:

    缩点变成一颗树之后,跑树的直径,然后把树的直径的两端连起来就行了

    代码:

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include<iostream>
      3 #include<stdio.h>
      4 #include<string.h>
      5 const int VM = 200005;
      6 const int EM = 1000005;
      7 
      8 struct Edeg
      9 {
     10     int to,nxt,vis;
     11 }edge[EM<<1],tree[EM<<1];
     12 
     13 int head[VM],vis[VM],thead[VM];
     14 int dfn[VM],low[VM],stack[VM],belong[VM];
     15 int ep,bridge,son,maxn,src,n,cnt,scc,top;
     16 int te[VM];
     17 int max (int a,int b)
     18 {
     19     return a > b ? a : b;
     20 }
     21 int min(int a ,int b)
     22 {
     23     return a > b ? b : a;
     24 }
     25 void addedge (int cu,int cv)
     26 {
     27     edge[ep].to = cv;
     28     edge[ep].vis = 0;
     29     edge[ep].nxt = head[cu];
     30     head[cu] = ep ++;
     31     edge[ep].to = cu;
     32     edge[ep].vis = 0;
     33     edge[ep].nxt = head[cv];
     34     head[cv] = ep ++;
     35 }
     36 void Buildtree(int cu,int cv)
     37 {
     38     tree[son].to = cv;
     39     tree[son].nxt = thead[cu];
     40     thead[cu] = son ++;
     41 }
     42 void Tarjan (int u)
     43 {
     44     int v;
     45     vis[u] = 1;
     46     dfn[u] = low[u] = ++cnt;
     47     stack[top++] = u;
     48     for (int i = head[u];i != -1;i = edge[i].nxt)
     49     {
     50         v = edge[i].to;
     51         if (edge[i].vis) continue; //
     52         edge[i].vis = edge[i^1].vis = 1; //正向边访问过了,反向边得标志,否则两点会成一块。
     53         if (vis[v] == 1)
     54             low[u] = min(low[u],dfn[v]);
     55         if (!vis[v])
     56         {
     57             Tarjan (v);
     58             low[u] = min(low[u],low[v]);
     59             if (low[v] > dfn[u])
     60                 bridge ++;
     61         }
     62     }
     63     if (dfn[u] == low[u])
     64     {
     65         ++scc;
     66         do{
     67             v = stack[--top];
     68             vis[v] = 0;
     69             belong[v] = scc;
     70             te[scc]=v;
     71         }while (u != v);
     72     }
     73 }
     74 void BFS(int u)
     75 {
     76     int que[VM+100];
     77     int front ,rear,i,v;
     78     front = rear = 0;
     79     memset (vis,0,sizeof(vis));
     80     que[rear++] = u;
     81     vis[u] = 1;
     82     while (front != rear)
     83     {
     84         u = que[front ++];
     85         front = front % (n+1);
     86         for (i = thead[u];i != -1;i = tree[i].nxt)
     87         {
     88             v = tree[i].to;
     89             if (vis[v]) continue;
     90             vis[v] = 1;
     91             que[rear++] = v;
     92             rear = rear%(n+1);
     93         }
     94     }
     95     src = que[--rear];//求出其中一个端点
     96 }
     97 int ans2=0;
     98 void DFS (int u,int dep)
     99 {
    100     if(maxn<dep)
    101     {
    102         maxn = max(maxn,dep);
    103         ans2 = u;
    104     }
    105     vis[u] = 1;
    106     for (int i = thead[u]; i != -1; i = tree[i].nxt)
    107     {
    108         int v = tree[i].to;
    109         if (!vis[v])
    110             DFS (v,dep+1);
    111     }
    112 }
    113 void solve()
    114 {
    115     int u,v;
    116     memset (vis,0,sizeof(vis));
    117     cnt = bridge = scc = top = 0;
    118     Tarjan (1);
    119     memset (thead,-1,sizeof(thead));
    120     son = 0;
    121     for (u = 1;u <= n;u ++)              //重构图
    122         for (int i = head[u];i != -1;i = edge[i].nxt)
    123         {
    124             v = edge[i].to;
    125             if (belong[u]!=belong[v])
    126             {
    127                 Buildtree (belong[u],belong[v]);
    128                 Buildtree (belong[v],belong[u]);
    129             }
    130         }
    131     maxn = 0;    //最长直径
    132     BFS(1);      //求树直径的一个端点
    133     memset (vis,0,sizeof(vis));
    134     DFS(src,0); //求树的最长直径
    135     printf("%d %d
    ",te[src],te[ans2]);
    136     //printf ("%d
    ",bridge-maxn);
    137 }
    138 
    139 int main ()
    140 {
    141     freopen("input.txt","r",stdin);
    142     freopen("output.txt","w",stdout);
    143     int m,u,v;
    144     while (~scanf ("%d%d",&n,&m))
    145     {
    146         if (n == 0&&m == 0)
    147             break;
    148         memset (head,-1,sizeof(head));
    149         ep = 0;
    150         while (m --)
    151         {
    152             scanf ("%d%d",&u,&v);
    153             addedge (u,v);
    154         }
    155         solve();
    156     }
    157     return 0;
    158 }
  • 相关阅读:
    基础薄弱的反思
    最短路SPFA
    乌龟棋
    石子归并
    Linux学习2
    java 基础 数组
    java 基础 异常
    java 基础 接口
    java 基础 instance of
    solidity“abi.encode/abi.encodePacked”使用golang编码
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4780571.html
Copyright © 2011-2022 走看看