• 【jzoj3773】小P的烦恼


    题目描述
            小 P 最近遇上了大麻烦,他的高等代数挂科了。于是他只好找高代老师求情。善良的高代老师答应不挂他,但是要求小 P 帮助他一起解决一个难题。
            问题是这样的,高代老师近期要组织班上同学一起去漂流,漂流可以看做是在一张 n 个点 m 条边的有向无环图上进行的,点编号从 0 到 n-1 ,表示景点; 边是连接各景点的一定长度的河道。同时,定义编号为 s 是起点而 t 是终点。我们不妨把从 s 点到 t 点不论走什么样的路径都需要经过的边称为桥, 这些桥由于地势险要所以是危险的。现在高代老师有两条长度为 l 的安全绳,他希望用这两条安全绳覆盖尽可能长的桥,使得他们通过的桥的长度之和尽量短。

    输入
            本题包含多组数据,第一行是一个数 T(T<=5)表示数据组数,对于每组数据,第一行是 5 个数,n,m,s,t,l。
            以下 m 行,每行包括三个数 si,ti,pi,表示从 si 到 ti 有一条长度为 pi 的单向边。

    输出
         对于每组数据,输出一行,包括一个整数,为最优情况下通过的桥的长度之和。如果不存在从 s 到 t 的路径,请输出-1。

    输入样例
    1
    8 9 0 7 7
    0 4 1
    0 1 10
    1 2 9
    4 2 2
    2 5 8
    4 3 3
    5 6 6
    5 6 7
    6 7 5

    输出样例
    1

    数据范围
    对于 10%的数据,n<=10,m<=20
    对于 30%的数据,n<=1000,m<= 10000
    对于 100%的数据,n<=100000, m<=200000,0<=s,t,si,ti<n, l<=10^9,pi<=1000

    思路

      emmmmmmm当时这是第三题,第一题用奇怪的方法水过了,第二题一看推不出式子,就不弄啦啦啦

      这题,一看应该能分成两步。
      1、找桥
      2、找最大覆盖方案

    找桥?
      有关连通性的tarjan算法可以解决。    
      但我考场上不会。
      再一看,有向无环图,有戏,可以考虑乱搞。首先想到拓扑,桥的起点和终点至少应是拓扑序相邻的。但相邻的怎样才是桥呢?画个数轴吧。



      不是桥的那些边堆积在一起,而桥的位置只有一条边。好,我们现在需要找出相邻的,只有一条边覆盖的位置。在拓扑序上,一条边覆盖一个区间,可以用差分处理每条边就能求出覆盖数了。找桥完毕。

    找最大覆盖方案?
      在当时,我没有想出来,打了的找桥也相当于是废了……
      两条绳子不好弄吧?

    简化
      一条绳子怎么弄?
      再建一个数轴,从起点到终点,非桥、桥交错分布,非桥部分可以预处理最短路。
      绳子结尾位置确定了,那覆盖的长度就确定了。绳子结尾在哪?

      分情况讨论


      所以,绳子结尾在一个区间内可以等价为在一个区间的结尾。
      如何确定覆盖长度?
      用双指针可以扫出绳子能往前延伸至哪个区间,用前缀和就能求答案啦。

    回归
      两条绳子怎么弄?

      如果两条绳子完全分属不同的区间,那么枚举,在一条绳子的基础上,加上这条绳子起点前一条绳子能覆盖的最大值就行了吧。
      如果后面绳子的头接着前面绳子的尾呢?



      仍等价于两倍长度的绳子!

      记f[i][j]为,以1到i号区间为结尾,j条绳子能覆盖的最大值;预处理的g[i][j]为以i号区间为结尾,长度为j的绳子能覆盖多长;pre[i]为以i号区间为结尾的绳子的起点。
      最后的方程为
      f[i][1]=min(f[i-1][1],g[i][l]);
      f[i][2]=min(f[i-1][2],f[pre[i]-1][1]+g[i][l],g[i][2l]).

    找桥的其他方案
      我这个蒟蒻自己想到了这些方法,秉着分享思路的理念写了这个玩意。我在此不打算写有关tarjan的内容。
      针对有向无环图,从起点到桥的起点的方案数*桥的终点到终点的方案数=从起点到终点的总方案数。可根据此点找桥。

    代码
      WA,这种傻方法,我写的这么长,就不放了吧QWQ

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <cstring>
      7 #include <string>
      8 #include <queue>
      9 using namespace std;
     10 
     11 struct line
     12 {
     13     int to,next,w;
     14 }e[200050];
     15 
     16 int fl[100050],enfl[100050],inp[100050],outp[100050],hd[100050],q[100050],srt[100050],brst[100050],bren[100050],brw[100050];
     17 int t,n,m,st,en,i,j,k,x,y,z,l,tot,head,tail,cntzero,brtot,srtot,etot;
     18 int ek[400050],sumk[400050],ef[400050],sumf[400050];
     19 int dp[400050][3],pre[400050][2];
     20 
     21 void ins(int p,int s,int r)
     22 {
     23     tot++; e[tot].to=s; e[tot].next=hd[p]; e[tot].w=r; hd[p]=tot;
     24     inp[s]++; outp[p]++;
     25 }
     26 
     27 void dfs(int p)
     28 {
     29     fl[p]=1;
     30     if (p==en) return;
     31     int i1=hd[p];
     32     while (i1!=-1)
     33     {
     34         if (fl[e[i1].to]==0) dfs(e[i1].to);
     35         if (enfl[e[i1].to]==1) enfl[p]=1;
     36         if (enfl[e[i1].to]==0) {outp[p]--; inp[e[i1].to]--;}
     37         i1=e[i1].next;
     38     }
     39 }
     40 
     41 void tuopu()
     42 {
     43     brtot=0;
     44     memset(q,0,sizeof(q));
     45     memset(fl,0,sizeof(fl));
     46     memset(srt,0,sizeof(srt));
     47     head=0; tail=0; srtot=0;
     48     for (i=0;i<=n-1;i++) 
     49         if (enfl[i]==1)
     50             if (inp[i]==0) {q[tail]=i; tail++; }
     51     while (head<tail)
     52     {
     53         i=q[head]; 
     54         srtot++; srt[srtot]=i; fl[i]=srtot;
     55         j=hd[i];
     56         while (j!=-1)
     57         {
     58             if (enfl[e[j].to]==1)
     59             {
     60                 inp[e[j].to]--; outp[i]--;
     61                 if (inp[e[j].to]==0) {q[tail]=e[j].to; tail++;}
     62             }
     63             j=e[j].next;
     64         }
     65         head++;
     66     }
     67 }
     68 
     69 void findbridge()
     70 {
     71     memset(q,0,sizeof(q));
     72     memset(inp,0,sizeof(inp));
     73     for (i=0;i<=n-1;i++)
     74         if (enfl[i]==1)
     75         {
     76             j=hd[i];
     77             while (j!=-1)
     78             {
     79                 if (enfl[e[j].to]==1) 
     80                 {
     81                     q[fl[i]-1]++; q[fl[e[j].to]-1]--;
     82                 }
     83                 j=e[j].next;
     84             }
     85         }
     86 
     87     inp[0]=q[0];
     88     for (i=1;i<=srtot;i++) inp[i]=inp[i-1]+q[i];
     89 
     90     for (int i1=1;i1<=srtot;i1++)
     91     {
     92         i=srt[i1];
     93         if (enfl[i]==1)
     94         {
     95             j=hd[i];
     96             while (j!=-1)
     97             {
     98                 if (enfl[e[j].to]==1) 
     99                 {
    100                     if ((fl[e[j].to]-fl[i]==1)&&(inp[fl[i]-1]==1))
    101                     {
    102                         brtot++; brst[brtot]=i; bren[brtot]=e[j].to; brw[brtot]=e[j].w;
    103                     }
    104                 }
    105                 j=e[j].next;
    106             }
    107         }    
    108     }
    109 }
    110 
    111 int sp(int p,int r)
    112 {
    113     int i1,j1,k1;
    114     for (i1=fl[p];i1<=fl[r];i1++) q[i1]=1<<30;
    115     q[fl[p]]=0;
    116     for (i1=fl[p];i1<=fl[r]-1;i1++) 
    117     {
    118         j1=srt[i1]; k1=hd[j1]; 
    119         while (k1!=-1) 
    120         {
    121             if (enfl[e[k1].to]==1) q[fl[e[k1].to]]=min(q[fl[e[k1].to]],q[i1]+e[k1].w);
    122             k1=e[k1].next;
    123         } 
    124     }
    125     return q[fl[r]];
    126 }
    127 
    128 void countt()
    129 {
    130     if (brtot==0) {cout<<0<<endl; return;}
    131     sumk[0]=0; sumf[0]=0;
    132     for (i=1;i<=brtot-1;i++) 
    133     {
    134         ek[2*i-1]=brw[i]; ek[2*i]=sp(bren[i],brst[i+1]); 
    135         ef[2*i-1]=brw[i]; ef[2*i]=0;
    136     }
    137     ek[2*brtot-1]=brw[brtot]; ef[2*brtot-1]=brw[brtot];
    138     for (i=1;i<=2*brtot-1;i++) {sumk[i]=ek[i]+sumk[i-1]; sumf[i]=ef[i]+sumf[i-1];}
    139     int ll,rr,sum1,sum2;
    140     sum1=0; ll=1; rr=1;
    141     while (rr<=2*brtot-1)
    142     {
    143         sum1+=ek[rr]; 
    144         while (sum1>l) 
    145         {
    146             sum1-=ek[ll]; ll++;
    147         }
    148         pre[rr][0]=ll;
    149         rr++;
    150     }
    151     
    152     sum1=0; ll=1; rr=1;
    153     while (rr<=2*brtot-1)
    154     {
    155         sum1+=ek[rr]; 
    156         while (sum1>2*l) 
    157         {
    158             sum1-=ek[ll]; ll++;
    159         }
    160         pre[rr][1]=ll;
    161         rr++;
    162     }
    163     
    164     dp[0][0]=0;
    165     for (i=1;i<=2*brtot-1;i++)
    166     {
    167         sum1=sumf[i]-sumf[pre[i][0]-1];
    168         sum2=sumk[i]-sumk[pre[i][0]-1];
    169         if ((pre[i][0]-1)%2==1) sum1+=l-sum2;
    170         dp[i][1]=sum1;
    171         dp[i][0]=max(dp[i-1][0],dp[i][1]);
    172     }
    173     
    174     dp[0][2]=0;
    175     for (i=1;i<=2*brtot-1;i++)
    176     {
    177         sum1=sumf[i]-sumf[pre[i][1]-1];
    178         sum2=sumk[i]-sumk[pre[i][1]-1];
    179         if ((pre[i][1]-1)%2==1) sum1+=l-sum2;
    180         dp[i][2]=max(dp[i-1][2],sum1);
    181         dp[i][2]=max(dp[i][2],dp[i][1]+dp[pre[i][0]-2][0]);
    182     }
    183     cout<<sumf[2*brtot-1]-dp[2*brtot-1][2]<<endl;
    184 }
    185 
    186 int main()
    187 {
    188     cin>>t;
    189     for (k=1;k<=t;k++)
    190     {
    191         cin>>n>>m>>st>>en>>l;
    192         for (i=0;i<=n-1;i++) hd[i]=-1;
    193         tot=0;
    194         memset(inp,0,sizeof(inp));
    195         memset(outp,0,sizeof(outp));
    196         for (i=1;i<=m;i++)
    197         {
    198             cin>>x>>y>>z;
    199             ins(x,y,z);
    200         }
    201         
    202         memset(fl,0,sizeof(fl));
    203         memset(enfl,0,sizeof(enfl));
    204         enfl[en]=1;
    205         dfs(st);
    206         if (enfl[st]==0) {cout<<-1<<endl; continue;}
    207         for (i=0;i<=n-1;i++)
    208             if (enfl[i]==0)
    209             {
    210                 j=hd[i];
    211                 while (j!=-1)
    212                 {
    213                     outp[i]--; inp[e[j].to]--;
    214                     j=e[j].next;
    215                 }
    216             }
    217     
    218         tuopu();
    219         
    220         findbridge();
    221         
    222         countt();
    223     }
    224 }
    独(luan)特(gao)的做法
  • 相关阅读:
    Maven_自动化构建和构建环节
    Maven_运行时环境
    构建的概念
    Maven_真的需要吗?
    28)拷贝构造函数
    27)构造和析构函数
    26)多文件形式编写类步骤
    25)类的封装
    24)类
    23)函数重载和函数指针
  • 原文地址:https://www.cnblogs.com/Krain428571/p/7368194.html
Copyright © 2020-2023  润新知