zoukankan      html  css  js  c++  java
  • 边双联通分量

    (noip模拟赛)化学竞赛的大奖

    (prize.pas/c/cpp)


    【问题描述】


    XYX 在 CChO(全国化学奥林匹克竞赛)比赛中获得了大奖,奖品是一张特殊的机票。
    使用这张机票,可以在任意一个国家内的任意城市之间的免费飞行,只有跨国飞行时才
    会有额外的费用。XYX 获得了一张地图,地图上有城市之间的飞机航班和费用。已知从
    每个城市出发能到达所有城市,两个城市之间可能有不止一个航班。一个国家内的每两
    个城市之间一定有不止一条飞行路线, 而两个国家的城市之间只 有一条飞行路线。 XYX
    想知道, 从每个城市出发到额外费用最大的城市, 以便估算出出行的费用, 请你帮助他。
    当然,你不能通过乘坐多次一个航班增加额外费用, 也就是必须沿费用最少的路线飞
    行。


    【输入】


    第一行,两个整数 N,M,表示地图上有 N 个城市,M 条航线。
    接下来 M 行,每行三个整数 a,b,c,表示城市 a,b 之间有一条费用为 c 的航线。


    【输出】

    共 N 行,第 i 行为从城市 i 出发到达每个城市额外费用的最大值。


    【输入输出样例 1】

    输入

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

    输出






    7


    有四个国家,包含的城市分别为 {1,2,3},{4},{5},{6}。
    从城市 1 出发到达城市 6,乘坐(1,3)(3,6)两个航班费用最大,
    (1,3)在国内为免费航班,(3,6)的费用为 4,所以从 1 出发的最
    大费用为 4。


    【数据范围】


    对于 40%的数据 1<=N<=1000,1<=M<=1000
    对于 100%的数据 1<=N<=20000,1<=M<=200000

    分析

    模拟赛的一道题,感觉像tarjan缩点,但这是无向图,

    但是思想是一样的,所以写了一个乱搞的tarjan,居然a了。。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 
      8 const int N = 50010;
      9 const int M = 500100;
     10 
     11 struct Edge{
     12     int to,w,nxt;
     13     bool flag;
     14     Edge() {flag = false;}
     15 }e[M],t[M];
     16 int head[N],tot = 1,headt[N],tott;
     17 int dfn[N],low[N],st[N],top;
     18 int bel[N],dp[N][3],ans[N];
     19 bool vis[N];
     20 int tn,cnt;
     21 
     22 inline int read() {
     23     int x = 0,f =1;char ch = getchar();
     24     for (; ch<'0'||ch>'9'; ch = getchar())
     25         if (ch=='-') f = -1;
     26     for (; ch>='0'&&ch<='9'; ch = getchar())
     27         x = x*10+ch-'0';
     28     return x*f;
     29 }
     30 
     31 
     32 void tarjan(int u,int fa) {
     33     dfn[u] = low[u] = ++tn;
     34     st[++top] = u;
     35     vis[u] = true;
     36     
     37     for (int i=head[u]; i; i=e[i].nxt) {
     38         int v = e[i].to;
     39         if (!dfn[v]) {
     40             e[i^1].flag = true;
     41             tarjan(v,u);
     42             low[u] = min(low[u],low[v]);
     43         }
     44         else {
     45             if (vis[v] && !e[i].flag) low[u] = min(low[u],dfn[v]);
     46         }
     47     }
     48     
     49     if (dfn[u]==low[u]) {
     50         ++cnt;
     51         do {
     52             vis[st[top]] = false;
     53             bel[st[top]] = cnt;
     54             top--;            
     55         }while (st[top+1]!=u);
     56     }
     57 }
     58 
     59 
     60 inline void add_edge(int u,int v,int w) {
     61     t[++tott].to = v,t[tott].w = w,t[tott].nxt = headt[u],headt[u] = tott;
     62     t[++tott].to = u,t[tott].w = w,t[tott].nxt = headt[v],headt[v] = tott;
     63 }
     64 
     65 void dfs(int u,int fa) {
     66     int ts = headt[u];
     67     for (int i=headt[u]; i; i=t[i].nxt) {
     68         int v = t[i].to;
     69         if (v==fa) continue;
     70         if (vis[v]) continue;
     71         vis[v] = true;
     72         dfs(v,u);
     73         if (dp[v][0] + t[i].w > dp[u][0]) {
     74             dp[u][1] = dp[u][0];
     75             dp[u][0] = dp[v][0]+t[i].w;
     76         }
     77         else if (dp[v][0]+t[i].w > dp[u][1]) 
     78             dp[u][1] = dp[v][0]+t[i].w;
     79     }
     80 }
     81 void dfs2(int u,int fa) {
     82     
     83     for (int i=headt[u]; i; i=t[i].nxt) {
     84         int v = t[i].to;
     85         if (v==fa) continue;
     86         if (vis[v]) continue;
     87         vis[v] = true;
     88         if (dp[v][0]+t[i].w==dp[u][0]) 
     89             dp[v][2] = max(dp[u][2],dp[u][1])+t[i].w;
     90         else dp[v][2] = max(dp[u][2],dp[u][0])+t[i].w;
     91         dfs2(v,u);
     92     }
     93 }
     94 
     95 int main() {
     96     
     97     freopen("prize.in","r",stdin);
     98     freopen("prize.out","w",stdout);
     99     
    100     int n = read(),m = read();
    101     for (int u,v,w,i=1; i<=m; ++i) {
    102         u = read(),v = read(),w = read();
    103         e[++tot].to = v,e[tot].w = w,e[tot].nxt = head[u],head[u] = tot;
    104         e[++tot].to = u,e[tot].w = w,e[tot].nxt = head[v],head[v] = tot;
    105     }
    106     
    107     /*for (int i=1; i<=n; ++i) 
    108         if (!dfn[i]) */
    109     tarjan(1,0);
    110     
    111 //    for (int i=1; i<=n; ++i) printf("%d ",bel[i]);    
    112     for (int i=1; i<=n; ++i) 
    113         for (int j=head[i]; j; j=e[j].nxt) 
    114             add_edge(bel[i],bel[e[j].to],e[j].w);
    115     
    116 /*    for (int i=1; i<=4; ++i) {
    117         printf("%d",headt[i]);
    118     //    for (int j=headt[i]; j; j=t[j].nxt) 
    119     //        printf("%d ",t[j].to);
    120         printf("
    ");
    121         
    122     }*/
    123     memset(vis,false,sizeof(vis));
    124     vis[1] = true;
    125     dfs(1,0);
    126     memset(vis,false,sizeof(vis));
    127     vis[1] = true;
    128     dfs2(1,0);
    129     
    130     for (int i=1; i<=cnt; ++i) 
    131         ans[i] = max(dp[i][0],dp[i][2]);
    132 
    133     for (int i=1; i<=n; ++i) 
    134         printf("%d
    ",ans[bel[i]]);
    135     return 0;
    136 }
    137 /*
    138 
    139 6 6
    140 1 4 2
    141 1 2 6
    142 2 5 3
    143 2 3 7
    144 6 3 4
    145 3 1 8
    146 
    147 
    148 6 6
    149 1 2 1
    150 2 3 1
    151 2 4 1
    152 3 5 1
    153 4 5 1
    154 5 6 1
    155 
    156 6 7
    157 1 2 3
    158 2 3 1
    159 3 4 1
    160 4 5 1
    161 2 5 1
    162 4 2 1
    163 4 6 2
    164 
    165 7 9
    166 1 2 3
    167 2 3 1
    168 3 4 1
    169 4 5 1
    170 2 5 1
    171 4 2 1
    172 4 6 2
    173 3 7 1
    174 4 7 1
    175 
    176 */
    View Code

    后来知道是边双联通分量。。

    概念:任意两点至少存在两条边不重复路径

      1 #include<bits/stdc++.h>
      2 #define maxn 20005
      3 #define maxm 200005
      4 using namespace std;
      5 
      6 int n,m,id,dfn[maxn],low[maxn],head[maxn],head2[maxn],cnt;
      7 int dis[maxn],dis1[maxn],mx=0,root;
      8 int belong[maxn],belnum;
      9 bool vis[maxn];
     10 stack<int> stk;
     11 struct Edge{    
     12 int u,v,val,next;
     13 }edge[maxm<<1],e[maxm<<1];
     14 
     15 inline int read()
     16 {
     17     int x=0,f=1;char c=getchar();
     18     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     19     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     20     return x*f;
     21 }
     22 namespace Tarjan
     23 { 
     24 
     25 inline void add(int u,int v,int val)
     26 {    
     27     edge[++cnt].v=v;    
     28     edge[cnt].u=u;    
     29     edge[cnt].val=val;    
     30     edge[cnt].next=head[u];    
     31     head[u]=cnt;
     32 } 
     33 
     34 inline void tarjan(int u,int fa)
     35 {    
     36     dfn[u]=low[u]=++id;    
     37     vis[u]=1;    
     38     stk.push(u);    
     39     for(int i=head[u];i!=-1;i=edge[i].next)    
     40     {    
     41         int v=edge[i].v;    
     42         if(!dfn[v])    
     43         {    
     44             tarjan(v,u);    
     45             low[u]=min(low[u],low[v]);    
     46         }    
     47         else if(vis[v]&&v!=fa)    
     48         {    
     49             low[u]=min(low[u],dfn[v]);    
     50         }    
     51     }    
     52     if(dfn[u]==low[u])    
     53     {    
     54         belnum++;    
     55         int temp;    
     56         do{    
     57             temp=stk.top();    
     58             belong[temp]=belnum;    
     59             vis[temp]=0;    
     60             stk.pop();    
     61         }while(temp!=u);    
     62     }
     63 } 
     64 
     65 inline void solve1()
     66 {    
     67     memset(head,-1,sizeof(head));    
     68     for(int i=1,u,v,val;i<=m;i++)    
     69     {    
     70         u=read();v=read();val=read();    
     71         add(u,v,val);add(v,u,val);    
     72     }    
     73     for(int i=1;i<=n;i++)    
     74     {    
     75         if(!dfn[i])    tarjan(i,0);    
     76     }
     77 } 
     78 
     79 } 
     80 
     81 namespace LP
     82 { 
     83 
     84 inline void Add(int u,int v,int val)
     85 {    
     86     e[++cnt].v=v;    
     87     e[cnt].val=val;    
     88     e[cnt].next=head2[u];    
     89     head2[u]=cnt;
     90 } 
     91 
     92 void dfs1(int u,int fa)
     93 {    
     94     for(int i=head2[u];i!=-1;i=e[i].next)    
     95     {    
     96         int v=e[i].v;    
     97         if(v==fa)    continue;    
     98         dis[v]=dis[u]+e[i].val;    
     99         if(dis[v]>mx)    mx=dis[v],root=v;    
    100         dfs1(v,u);    
    101     }
    102 } 
    103 
    104 void dfs2(int u,int fa)
    105 {    
    106     for(int i=head2[u];i!=-1;i=e[i].next)    
    107     {    
    108         int v=e[i].v;    
    109         if(v==fa)    continue;    
    110         dis1[v]=dis1[u]+e[i].val;    
    111         dfs2(v,u);    
    112     }
    113 } 
    114 
    115 inline void solve2()
    116 {    
    117     cnt=0;    
    118     memset(head2,-1,sizeof(head2));    
    119     for(int i=1;i<=n;i++)    
    120         for(int j=head[i];j!=-1;j=edge[j].next)    
    121         {    
    122             if(belong[i]!=belong[edge[j].v])    
    123                 Add(belong[i],belong[edge[j].v],edge[j].val);    
    124         }    
    125     dfs1(1,-1);    
    126     mx=0;memset(dis,0,sizeof(dis));    
    127     dfs1(root,-1);    
    128     mx=0;    
    129     dfs2(root,-1);    
    130     for(int i=1;i<=n;i++)    
    131         printf("%d
    ",max(dis[belong[i]],dis1[belong[i]]));
    132 } 
    133     
    134 }
    135 int main()
    136 {    
    137     freopen("prize.in","r",stdin);
    138     freopen("prize.out","w",stdout);
    139     n=read();m=read();    
    140     Tarjan::solve1();    
    141     LP::solve2();    
    142     return 0;
    143 }
    View Code
  • 相关阅读:
    Jupyter-notebook安装问题及解决
    [模块] scrapy_splash(迁移)
    pychram-redis破解
    scrapy-redis(迁移)
    123
    day44作业
    sql 的基本数据类型
    基本数据库操作
    安装数据库与配置使用环境
    线程知识点——Event事件
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7894362.html
Copyright © 2011-2022 走看看