首页 > 代码库 > BZOJ 1927 星际竞速

BZOJ 1927 星际竞速

每个点可以由a[i],走边 两种形式到达。于是拆点,在右边直连汇点,和连图中的边,从而表达了“或”的含义。

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#define maxv 1650#define maxe 500500#define inf 2000000000using namespace std;int n,m,a[maxv],x,y,z,nume=1,g[maxv],s,t;int dis[maxv],prev[maxv],pree[maxv];bool vis[maxv];queue <int> q;struct edge{    int v,f,c,nxt;}e[maxe];void addedge(int u,int v,int f,int c){    e[++nume].v=v;e[nume].f=f;e[nume].c=c;e[nume].nxt=g[u];g[u]=nume;    e[++nume].v=u;e[nume].f=0;e[nume].c=-c;e[nume].nxt=g[v];g[v]=nume;}bool spfa(){    for (int i=s;i<=t;i++) {vis[i]=false;dis[i]=inf;prev[i]=pree[i]=-1;}    vis[s]=true;dis[s]=0;q.push(s);    while (!q.empty())    {        int head=q.front();q.pop();vis[head]=false;        for (int i=g[head];i;i=e[i].nxt)        {            int v=e[i].v;            if ((e[i].f>0) && (dis[v]>dis[head]+e[i].c))            {                dis[v]=dis[head]+e[i].c;                 prev[v]=head;pree[v]=i;                if (!vis[v]) {vis[v]=true;q.push(v);}            }        }    }    if (dis[t]==inf) return false;    return true;}int dinic(){    int u=t,dt=inf;    while (u!=s)    {        dt=min(dt,e[pree[u]].f);        u=prev[u];    }    u=t;    while (u!=s)    {        e[pree[u]].f-=dt;e[pree[u]^1].f+=dt;        u=prev[u];    }    return dis[t]*dt;}int main(){    scanf("%d%d",&n,&m);s=0;t=2*n+1;    for (int i=1;i<=n;i++)    {        scanf("%d",&a[i]);        addedge(s,i,1,0);        addedge(i+n,t,1,0);        addedge(s,i+n,1,a[i]);    }    for (int i=1;i<=m;i++)    {        scanf("%d%d%d",&x,&y,&z);        if (x>y) swap(x,y);        addedge(x,y+n,1,z);    }    int min_cost=0;    while (spfa())        min_cost+=dinic();    printf("%d\n",min_cost);    return 0;}

 

BZOJ 1927 星际竞速