• P6033 Ryoku 的探索 (基环树)


    题目链接

     题解:

    图为一个基环树。

    dfs找到环,对于环上的每一个点u, 确定与它连接的具有最小美观度的边的长度w, 把这个w值更新到与它连接的其他非环上点(minval[]数组),则u和与它连接的其他非环上点的答案即为所有边长度只和减去minval[i]。

    Code:

      1 #include <bits/stdc++.h>
      2 # define LL long long
      3 using namespace std;
      4 
      5 const int maxn=1000000+10;
      6 const int INF=0x7fffffff;
      7 struct Edge{
      8     int v,next,w,p;
      9 }e[maxn<<1];
     10 int head[maxn];
     11 int en;
     12 
     13 int n;
     14 int incycle[maxn];
     15 int instack[maxn];
     16 stack<int> stk;
     17 bool hasfind;
     18 int minval[maxn];
     19 
     20 
     21 void add(int from, int to, int w, int p){
     22     e[en].v=to;
     23     e[en].next=head[from];
     24     e[en].w=w;
     25     e[en].p=p;
     26     head[from]=en;
     27     ++en;
     28 }
     29 
     30 void dfs(int u, int pre){
     31     if(hasfind) return;
     32     if(instack[u]==1){
     33         while(stk.top()!=u){
     34             int t=stk.top();
     35             stk.pop();
     36             incycle[t]=1;
     37             instack[t]=0;
     38         }
     39         stk.pop();
     40         instack[u]=0;
     41         incycle[u]=1;
     42         hasfind=true;
     43         return;
     44     }
     45     instack[u]=1;
     46     stk.push(u);
     47     for(int i=head[u];i!=-1;i=e[i].next){
     48         int v=e[i].v;
     49         if(v==pre) continue;
     50         dfs(v,u);
     51     }
     52     stk.pop();
     53     instack[u]=0;
     54 }
     55 
     56 void setvalue(int u, int val){
     57     minval[u]=val;
     58     for(int i=head[u];i!=-1;i=e[i].next){
     59         int to=e[i].v;
     60         if(incycle[to]==0 && minval[to]==-1){
     61             setvalue(to,val);
     62         }
     63     }
     64 }
     65 
     66 int main(){
     67     memset(head,-1,sizeof(head));
     68     memset(minval,-1,sizeof(minval));
     69     scanf("%d", &n);
     70     LL total=0;
     71     for(int i=1;i<=n;++i){
     72         int a,b,c,d;
     73         scanf("%d %d %d %d", &a, &b, &c, &d);
     74         total+=c;
     75         add(a,b,c,d);
     76         add(b,a,c,d);
     77     }
     78     hasfind=false;
     79     dfs(1,0);
     80 
     81     for(int i=1;i<=n;++i){
     82         if(incycle[i]==1){
     83             int minp=INF;
     84             int minw=0;
     85             for(int j=head[i];j!=-1;j=e[j].next){
     86                 int to=e[j].v;
     87                 if(incycle[to]==1){
     88                     if(e[j].p<minp){
     89                         minp=e[j].p;
     90                         minw=e[j].w;
     91                     }
     92                 }
     93             }
     94             setvalue(i,minw);
     95         }
     96     }
     97 
     98     for(int i=1;i<=n;++i){
     99         printf("%lld
    ", total-minval[i]);
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    离散数学概论
    Linux内核分析
    程序的本质
    常见bug分析
    java编程思想--学习心得
    领域特定语言--心得
    Linux下网卡配置
    ubuntu下安装python的gevent模块遇到的一个问题
    二分图的最小点覆盖和最大独立集
    win7通过ssh远程登录mininet虚拟机,运行wireshark并通过x11在宿主机显示图形界面
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12246456.html
Copyright © 2020-2023  润新知