• UVA 11865 Stream My Contest(最小树形图)


    题意:N台机器,M条有向边,总资金C,现要到搭建一个以0号机(服务器)为跟的网路,已知每条网线可以把数据从u传递到v,其带宽为d,花费为c,且d越大,传输速度越快,问能够搭建的传输速度最快的网络d值是多少?(即:在C的支持下,网络中d的最小值最大是多少?)

    一开始把问题想简单了,以为网线可以随便接,其实是确定了u->v的= =

    最小树形图,概念蛮好理解的,要学习的话

    理论:http://hi.baidu.com/bin183/item/5d93ef69ceb541176895e682

    代码标注的很详细:http://blog.csdn.net/hehedounima/article/details/9320173

    其实,实质就是不断地缩点。需要注意的是选取以每个点为终点的最小边,以及重建图。

    因为看人家缩点部分的代码写得略挫,于是我就写了个更挫的T^T——基于强连通缩点的。。细节在代码里已经标明

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<vector>
      5 #include<queue>
      6 #include<stack>
      7 #include<algorithm>
      8 #define clr(a,m) memset(a,m,sizeof(a))
      9 #define rep(i,a,b) for(int i=a;i<=b;i++)
     10 using namespace std;
     11 
     12 const int MAXN=66;
     13 const int MAXM=11111;
     14 const int INF =1e9;
     15 
     16 struct Edge{
     17     int u,v,d,c;
     18 };
     19 
     20 int _n,m,w;
     21 int root,u[MAXM],v[MAXM],d[MAXM],c[MAXM];
     22 
     23 int head[MAXN],tol;
     24 
     25 int pre[MAXN],low[MAXN],sccno[MAXN],scc_cnt,dfs_clock;
     26 int stk[MAXN],top;
     27 
     28 bool mark[MAXN];
     29 Edge into[MAXN];
     30 
     31 vector<Edge>edge;
     32 vector<int>G[MAXN];
     33 
     34 void init()
     35 {
     36     edge.clear();
     37     rep(i,0,_n-1)//!!写成m-1,RE的泪啊
     38         G[i].clear();
     39 }
     40 
     41 void add(int u,int v,int d,int c)
     42 {
     43     edge.push_back((Edge){u,v,d,c});
     44     int m=edge.size();
     45     G[u].push_back(m-1);
     46 }
     47 
     48 void build()
     49 {
     50     rep(i,0,m-1)
     51         add(u[i],v[i],d[i],c[i]);
     52 }
     53 
     54 void rebuild()
     55 {
     56     rep(i,0,m-1){
     57         int v=edge[i].v;
     58         edge[i].u=sccno[edge[i].u];//自环会在处理into[]时省略
     59         edge[i].v=sccno[edge[i].v];
     60         if(edge[i].u!=edge[i].v)
     61             edge[i].c-=into[v].c;
     62     }
     63     root=sccno[root];//更新root、n的值
     64     _n=scc_cnt;
     65 }
     66 
     67 void dfs(int v)//因为into[]里是以终点v记录,所以反向缩点
     68 {
     69     int u;
     70     low[v]=pre[v]=dfs_clock++;
     71     stk[top++]=v;
     72 
     73     u=into[v].u;
     74     if(u!=root)//!!必不可少
     75         if(!pre[u]){
     76             dfs(u);
     77             low[v]=min(low[v],low[u]);
     78         }else if(!sccno[u])
     79             low[v]=min(low[v],pre[u]);
     80 
     81     if(low[v]==pre[v]){
     82         scc_cnt++;
     83         do{
     84             u=stk[--top];
     85             sccno[u]=scc_cnt;
     86         }while(u!=v);
     87     }
     88 }
     89 
     90 int find_scc()
     91 {
     92     scc_cnt=dfs_clock=0;
     93     clr(pre,0);
     94     clr(sccno,0);
     95 
     96     top=0;
     97     rep(i,1,_n)
     98         if(!pre[i])
     99             dfs(i);
    100     return scc_cnt;
    101 }
    102 
    103 bool DMST(int lim,int n)
    104 {
    105     _n=n;
    106 
    107     init();
    108     build();
    109     
    110     int cnt=0;
    111     while(1)
    112     {
    113         clr(mark,0);
    114         rep(i,0,m-1){
    115             if(edge[i].d<lim||edge[i].u==edge[i].v)//注意自环
    116                 continue;
    117             if(!mark[edge[i].v]){
    118                 into[edge[i].v]=(Edge){edge[i].u,edge[i].v,edge[i].d,edge[i].c};
    119                 mark[edge[i].v]=true;
    120             }else if(into[edge[i].v].c>edge[i].c)
    121                 into[edge[i].v]=(Edge){edge[i].u,edge[i].v,edge[i].d,edge[i].c};
    122         }
    123         into[root]=(Edge){root,root,0,0};//处理根
    124 
    125         rep(i,1,_n){//root的序号随缩点改变
    126             if(i==root)
    127                 continue;
    128             if(!mark[i]){
    129                 return false;
    130             }
    131             cnt+=into[i].c;
    132         }
    133         if(cnt>w)
    134             return false;
    135 
    136         if(find_scc()==_n)//若不成环
    137             return true;
    138         else
    139             rebuild();
    140     }
    141 }
    142 
    143 int main()
    144 {
    145     int T,n;
    146     scanf("%d",&T);
    147     while(T--)
    148     {
    149         int up=0,down=INF;
    150         scanf("%d%d%d",&n,&m,&w);
    151         root=1;
    152 
    153         rep(i,0,m-1){
    154             scanf("%d%d%d%d",&u[i],&v[i],&d[i],&c[i]);
    155             u[i]++;v[i]++;//注意scc_cnt是从1开始的,意味着所有的点都是1~n
    156             up=max(up,d[i]);
    157             down=min(down,d[i]);
    158         }
    159 
    160         if(!DMST(down,n)){
    161             printf("streaming not possible.
    ");
    162             continue;
    163         }
    164 
    165         int l=down,r=up;
    166         while(l<r)
    167         {
    168             int x=l+(r-l+1)/2;
    169             if(DMST(x,n))
    170                 l=x;
    171             else
    172                 r=x-1;
    173         }
    174         printf("%d kbps
    ",l);
    175     }
    176     return 0;
    177 }
    178 /*
    179 3
    180 7 15 29
    181 0 1 1 9
    182 0 4 1 5
    183 1 3 1 9
    184 1 2 1 3
    185 2 1 1 7
    186 2 6 1 6
    187 2 5 1 9
    188 3 0 1 3
    189 3 2 1 8
    190 3 5 1 5
    191 4 3 1 4
    192 5 4 1 3
    193 5 6 1 4
    194 6 2 1 4
    195 6 5 1 8
    196 */
    View Code
  • 相关阅读:
    源码0603-08-掌握-NSURLSession-上传
    源码0603-05-掌握-大文件下载
    源码0603-03-掌握-NSURLSession
    源码0603-01-了解-大文件下载(NSOutputStream)
    源码0602-10-掌握-文件上传11-了解-获得文件的MIMEType
    源码0602-08-掌握-解压缩
    源码0602-06-掌握-小文件下载-大文件下载
    用JS实现的控制页面前进、后退、停止、刷新以及加入收藏等功能
    java一路走来
    CKEditor3.5.3 JAVA下使用
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3284952.html
Copyright © 2020-2023  润新知