BZOJ 2324: [ZJOI2011] rescue Pikachu shortest + Cost Flow

title

BZOJ 2324
LUOGU 4542
Description

Rockets Pikachu was snatched by the evil plot! The three bad guys gave little wisdom left a red fruit provocation! In order to Pikachu, but also for justice, Ash and his friends were duty-bound to set foot on the road to rescue Pikachu.
There exists a strip M two-way road between the N stronghold stronghold Rockets. From 1 to N positions, respectively, numerals. Ash and his party really new K people from the town, to rescue trapped Pikachu N number of strongholds. For convenience, we will really new town regarded as strongholds 0, K individuals beginning at 0 points.
Due to heavy deployment Rockets, in order to destroy the stronghold K number, you must first destroy the order of K-1 No. 1 to the base, and, if the K-1 No. stronghold not destroyed, either due to the defensive nature of the chain, Ash and his party people entering the stronghold K, will be found, and have serious consequences. Therefore, before K-1 No. stronghold was destroyed, people are not able to go through any number K stronghold.
For simplicity, we ignore the part of the battle, Ash and his party anyone through K K No. No. stronghold that is considered strongholds were destroyed. The stronghold was destroyed can still be passed.
K individual is split up, as long as there is any one person after the K-1 No. stronghold was destroyed, after K No. stronghold, K No. stronghold was destroyed. Obviously, as long as No. N stronghold was destroyed, Pikachu would be saved.
Wild road is not safe, so little wisdom and his party at the same time want to destroy strongholds number N rescued Pikachu minimize the total length of at least K individuals through road.
Please help you design a little wisdom the best rescue plan now!

Input

The first line contains three positive integers N, M, K. It represents a total of N + 1 positions, respectively, undirected edges numbered from 0 to N, and the M. Ash and his party were beginning K individuals are located 0:00.
Next M rows, each row of three non-negative integer, the integer i-th row of Ai, Bi, Li. It indicates the presence of a base numbers from Ai to Bi length of a road base number of Li.

Output

It contains only one integer S, to rescue the smallest sum pikaqiu road that needs to elapse.

Sample Input

3 4 2
0 1 1
1 2 1
2 3 100
0 3 1

Sample Output

3
[] sample shows
a small intellectual and Xiaoxia together to rescue Pikachu. In the best scenario, starting with the small Chilean town went really new No. 1 o'clock, then went Depot II. When Ash succeeded in destroying the stronghold No. 2, Xiaoxia departure directly to the base 3, rescue Pikachu from a really new town.

HINT

To 100% data satisfy N ≤ 150, M ≤ 20 000, 1 ≤ K ≤ 10, Li ≤ 10 000, a line must be able to ensure Ash Pikachu rescued. As for why K ≤ 10, you may think that eventually the call of the ash, the ash, Xiaoxia, Xiaogang, Xiaojian, a small remote, a small victory, little light, Alice, Tin Tong, as well as travel to Japan the black sergeant, went to war with the Rockets.

Source

Day2

analysis

Simplify the meaning of the questions:

After using up \ (K \) section through \ (0 \) path to cover all the points.

Pretreatment, provided \ (d [i] [j ] \) represents the \ (I \) to \ (J \) without greater than \ (\ max (i, j ) \) shortest point, clearly you can use \ (floyed \) requirements.

Built map:

  1. Each point split point, even edge;
  2. Source to the point of even flow 0 \ (k \) side of the cost of 0, indicates that up after 0:00 \ (k \) times;
  3. A flow source connected to the remaining side of point costs for each point of 0;
  4. Each \ (I \) is the point \ (j (j> i) \) connected charges flow 1 \ (d [i] [j ] \) side;
  5. Each point of the 1 charges flow connected to the sink edge points 0;
  6. It can run a minimal cost.

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10,maxm=1e6+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f; 
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],cost[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
    ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>q;q.push(s);
    dist[s]=0,vis[s]=1,incf[s]=1<<30;
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x]; i; i=Next[i])
        {
            if (!edge[i]) continue;
            int y=ver[i];
            if (dist[y]>dist[x]+cost[i])
            {
                dist[y]=dist[x]+cost[i];
                incf[y]=min(incf[x],edge[i]);
                pre[y]=i;
                if (!vis[y]) q.push(y),vis[y]=1;
            }
        }
    }
    if (dist[t]==inf) return false;
    else return true;
}

long long maxflow,ans;
inline void update()
{
    int x=t;
    while (x!=s)
    {
        int i=pre[x];
        edge[i]-=incf[t];
        edge[i^1]+=incf[t];
        x=ver[i^1];
    }
    maxflow+=incf[t];
    ans+=dist[t]*incf[t];
}

int d[201][201];
int main()
{
    int n,m,k;read(n);read(m);read(k);
    for (int i=0; i<=n; ++i)
        for (int j=0; j<=n; ++j)
            if (i!=j) d[i][j]=inf;
    for (int i=1,x,y,z; i<=m; ++i) read(x),read(y),read(z),d[x][y]=d[y][x]=min(d[x][y],z);
    for (int k=0; k<=n; ++k)
        for (int i=0; i<=n; ++i)
            for (int j=0; j<=n; ++j)//这道题比较sb地把0点搞成图中的一个点
                if (k<max(i,j)) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);//floyed,保证经过点最大值<max(i,j)
    s=n<<1|1,t=s+1;
    for (int i=0; i<=n; ++i)
    {
        add(s,i,!i?k:1,0),add(i+n,t,1,0);//0点要保证k个人都过去
        for (int j=i+1; j<=n; ++j) add(i,j+n,1,d[i][j]);//i->j
    }
    while (spfa()) update();//好像没有上下界,只有上界乎?
    write(ans),puts("");
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11323265.html