nyoj 传纸条(一)

来源:互联网 发布:淘宝旧版本4.0.0下载 编辑:程序博客网 时间:2024/05/01 16:57
/*费用流,这道题的关键在于建图,看了一下大牛的博客,想了这道题总结一下思路;首先对于这种单一走路的题,一定要有拆点的思路对于这道题关建就在于拆点,首先让我们想一下,怎么让一个点只走一下呢,这就是插电的精髓然后加一条边,容量为 1,费用为当前数值的一条边,然后把这个点的右方下方的点加一条边,左上角顶点作为原点右下角顶点作为汇点,求一遍费用流就行。。。。*/#include<iostream>#include<queue>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn =  100000;const int inf = 0x777777;struct {    int head;}H[maxn];struct {    int u,v,next,cap,cost;}E[10*maxn];int top;void add(int u,int v,int cap,int cost) {    E[top].v = v;E[top].cap = cap;    E[top].cost = cost;    E[top].next = H[u].head;    H[u].head = top++;    E[top].v = u;    E[top].cap = 0;    E[top].cost = - cost;    E[top].next = H[v].head;    H[v].head = top++;}int d[maxn];int p[maxn];int vis[maxn];int path[maxn];int max_flow,ans;bool spfa(int s,int t,int n){    for(int i=1;i<=n;i++)        d[i]  = -inf;        d[s] = 0;        memset(vis,0,sizeof(vis));        queue <int> q;        q.push(s);vis[s] = 1;        while(!q.empty())        {            int x = q.front();q.pop();vis[x] = 0;            //cout<<x<<endl;            for(int i=H[x].head;i!=-1;i = E[i].next)            {                if(E[i].cap > 0 && d[E[i].v] < d[x]+E[i].cost)                {                    d[E[i].v] = d[x]+E[i].cost;                    path[E[i].v] = i;   //这个地方很是关键,记录当前边的编号                    p[E[i].v] = x;                    if(!vis[E[i].v])                    {                        vis[E[i].v] = 1;                        q.push(E[i].v);                    }                }            }        }        if(d[t] == -inf) return false;        int u = t,sum = inf;        while (u!=s) {            sum = min(E[path[u]].cap,sum);            u = p[u];        }        u = t;        max_flow += sum;        while(u != s) {     // 更新正反流量            E[path[u]].cap -= sum;            E[path[u]^1].cap += sum;            ans += E[path[u]].cost * sum;            u = p[u];        }        return true;}void init(){    memset(H,-1,sizeof(H));    memset(E,-1,sizeof(E));    top = 0;    ans = 0;    max_flow = 0;}int main(){    int n,m,k;    int u,v,cost,cap,num;    int T;    scanf("%d",&T);    while(T --)    {        init();        scanf("%d%d",&m,&n);        add(0,1,2,0);        add(2*(m*n-1),2*(m*n-1)+1,2,0);        for(int i=0;i<m;i++)        for(int j=0;j<n;j++)        {            scanf("%d",&num);            if(i > 0) add (2*((i-1)*n+j)+1,2*(i*n+j) ,1,0);            if(j > 0) add (2*(i*n+j-1)+1,2*(i*n+j),1,0);            if(!(i==0&&j==0)&&!(i==m-1&&j==n-1))                add(2*(i*n+j),2*(i*n+j)+1,1,num);        }        while(spfa(0,2*(m*n-1)+1,2*(n*m-1)+1));        cout<<ans<<endl;    }}

0 0
原创粉丝点击