zoukankan      html  css  js  c++  java
  • 4609: [Wf2016]Branch Assignment 最短路 DP (阅读理解题)

    Bzoj的翻译出锅了所以来官方题面:

    这个题应该是单向边而BZOJ说的是双向边,什么你WA了?谁叫你懒得看英文......

    显然我们能正向反向两遍SPFA处理出每个点到总部的距离和总部到每个点的距离。
    如果某个点所在的部门的大小为S,那么这个点需要送出S-1次消息并接收S-1次消息。
    我们把每个点的两个距离求和并排序,显然在一个块中的是这个序列上的一个区间(脑补一下为什么不这样不优),我们做一下前缀和。
    然后就开始DP了,f[i][j]表示前i个点分j个块,最小代价。f[i][j] = min( f[k][j-1] + ( i - k - 1 ) * ( sum[i] - sum[k] ) )。
    这个DP是O(n^3)的,考虑优化。
    显然更小的边权所在的块应该更大,所以我们能从区间[i-(i/j),i-1]枚举k,这样能优化到n^2logn。
    然而有更优美的做法:显然随着j增大,对于每个i最优的k也是递增的,直接指针扫过去,复杂度O(n^2)。
    两种做法都可以AC,反正我6代i5的机器上时间差异不大,不知道BZOJ能不能卡出来(我只交了第一种)。
    (为什么我现在在刷这种水题?我也不知道啊!!!)

    第一种代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 typedef long long int lli;
     7 using namespace std;
     8 const int maxn=5e3+1e2,maxe=5e4+1e2;
     9 
    10 lli su[maxn],f[2][maxn];
    11 int b,s,cur;
    12 
    13 struct Graph {
    14     int s[maxn],t[maxe],nxt[maxe],l[maxe],dis[maxn],inq[maxn],cnt;
    15     inline void addedge(int from,int to,int len) {
    16         t[++cnt] = to , l[cnt] = len , nxt[cnt] = s[from] , s[from] = cnt;
    17     }
    18     inline void spfa(int st) {
    19         memset(dis,0x3f,sizeof(dis)) , dis[st] = 0;
    20         queue<int> q; q.push(st) , inq[st] = 1;
    21         while( q.size() ) {
    22             const int pos = q.front(); q.pop() , inq[pos] = 0;
    23             for(int at=s[pos];at;at=nxt[at])
    24                 if( dis[t[at]] > dis[pos] + l[at] ) {
    25                     dis[t[at]] = dis[pos] + l[at];
    26                     if( !inq[t[at]] ) q.push(t[at]);
    27                 }
    28         }
    29     }
    30 }gra,rev;
    31 
    32 inline void dp() {
    33     for(int i=1;i<=b;i++) su[i] = (lli) gra.dis[i] + rev.dis[i];
    34     sort(su+1,su+1+b) , memset(f,0x3f,sizeof(f)) , **f = 0;
    35     for(int i=1;i<=b;i++) su[i] += su[i-1];
    36     for(int j=1;j<=s;j++) { // j is number of groups .
    37         cur ^= 1 , memset(f[cur],0x3f,sizeof(f[1]));
    38         for(int i=1;i<=b;i++) // i is last node .
    39             for(int lst=i/j;lst;lst--)
    40                 f[cur][i] = min( f[cur][i] , f[cur^1][i-lst] + ( lst - 1 ) * ( su[i] - su[i-lst] ) );
    41     }
    42 }
    43 
    44 int main() {
    45     static int n,r;
    46     scanf("%d%d%d%d",&n,&b,&s,&r);
    47     for(int i=1,a,b,l;i<=r;i++) scanf("%d%d%d",&a,&b,&l) , gra.addedge(a,b,l) , rev.addedge(b,a,l);
    48     gra.spfa(b+1) , rev.spfa(b+1) , dp();
    49     printf("%lld
    ",f[cur][b]);
    50     return 0;
    51 }
    View Code

    第二种代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 typedef long long int lli;
     7 using namespace std;
     8 const int maxn=5e3+1e2,maxe=5e4+1e2;
     9 
    10 int tp[maxn];
    11 lli su[maxn],f[2][maxn];
    12 int b,s,cur;
    13 
    14 struct Graph {
    15     int s[maxn],t[maxe],nxt[maxe],l[maxe],dis[maxn],inq[maxn],cnt;
    16     inline void addedge(int from,int to,int len) {
    17         t[++cnt] = to , l[cnt] = len , nxt[cnt] = s[from] , s[from] = cnt;
    18     }
    19     inline void spfa(int st) {
    20         memset(dis,0x3f,sizeof(dis)) , dis[st] = 0;
    21         queue<int> q; q.push(st) , inq[st] = 1;
    22         while( q.size() ) {
    23             const int pos = q.front(); q.pop() , inq[pos] = 0;
    24             for(int at=s[pos];at;at=nxt[at])
    25                 if( dis[t[at]] > dis[pos] + l[at] ) {
    26                     dis[t[at]] = dis[pos] + l[at];
    27                     if( !inq[t[at]] ) q.push(t[at]);
    28                 }
    29         }
    30     }
    31 }gra,rev;
    32 
    33 inline void dp() {
    34     for(int i=1;i<=b;i++) su[i] = (lli) gra.dis[i] + rev.dis[i];
    35     sort(su+1,su+1+b) , memset(f,0x3f,sizeof(f)) , **f = 0;
    36     for(int i=1;i<=b;i++) su[i] += su[i-1];
    37     for(int j=1;j<=s;j++) { // j is number of groups .
    38         cur ^= 1 , memset(f[cur],0x3f,sizeof(f[1]));
    39         for(int i=1;i<=b;i++) // i is last node .
    40             for(int lst=tp[i];lst<i;lst++)
    41                 if( f[cur][i] >= f[cur^1][lst] + ( i - lst - 1 ) * ( su[i] - su[lst] ) ) f[cur][i] = f[cur^1][lst] + ( i - lst - 1 ) * ( su[i] - su[lst] ) , tp[i] = lst;
    42     }
    43 }
    44 
    45 int main() {
    46     static int n,r;
    47     scanf("%d%d%d%d",&n,&b,&s,&r);
    48     for(int i=1,a,b,l;i<=r;i++) scanf("%d%d%d",&a,&b,&l) , gra.addedge(a,b,l) , rev.addedge(b,a,l);
    49     gra.spfa(b+1) , rev.spfa(b+1) , dp();
    50     printf("%lld
    ",f[cur][b]);
    51     return 0;
    52 }
    View Code


    良心的我给的数据下载:
    链接:https://pan.baidu.com/s/19EmgxmCYDASzpTaqr0alkA 密码:00qr

    果てないこの闇の向こうにも
    在无尽的这黑暗的对面
    光があると信じてる
    我相信也存在光明
    ここから生まれ変わる世界だけ
    从此只盯住这脱胎换骨的世界
    见つめて离さないよ
    目不转睛
    広がるこの空を见上げると
    仰望这广袤的天空
    あの日の戦いが映る
    那一日的决战映在脑海
    いつかは全て消えてしまうのか
    终有一天一切将会消失
    栄光を取り戻せ
    重新夺回这荣光

  • 相关阅读:
    easyExcel入门
    UML-从需求到设计--迭代进化
    UML-操作契约总结
    102. Binary Tree Level Order Traversal
    98. Validate Binary Search Tree
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    94. Binary Tree Inorder Traversal
    84. Largest Rectangle in Histogram
    92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8934081.html
Copyright © 2011-2022 走看看