您的位置:首页 > 其它

BZOJ1001 [Beijing2006] 狼抓兔子

2016-02-16 13:44 218 查看
相关资料:

浅析最大最小定理在信息学竞赛中的应用 北京大学ACM暑期课讲义-网络流

根据最大流-最小割定理,一个网络中,两个边缘点之间的最大流等于最小割(最小割就是用一条割线将两个点分割在两个图中,令删去的边的总权值最小。因此我们可以建图,将每个图(在本题中是每个三角形)作为一个点,点与点之间的连线就等于它们穿过的那条线的权值。在起点和终点间连一条线,线的内部和外部分别建立两个点,将这两个点和相邻的三角形连线,然后删去这条边在整个图中求最短路即可。

代码: (ps:当时也是在学习的过程中,所以借鉴了别人的代码)

#include <iostream>

#include <cstring>

#include <cstdio>

#include <queue>

using namespace std;

const int N=2000006, INF=0x3fffffff, E=N*3;

struct ARC {

    int u, val, next;

    inline void init(int a, int b, int c) {

        u=a, val=b, next=c;

    }

} arc[E];

int head
, tot, S, T, n, m, dis
;

bool vs
;

inline void add_arc(int s, int t, int val) {

    arc[tot].init(t, val, head[s]);

    head[s]=tot++;

}

void SPFA(){

     queue<int> q;

     fill(dis, dis+T+1, INF);

     fill(vs, vs+T+1, 0);

     q.push(S);

     dis[S]=S,vs[S]=true;

     while (!q.empty()){

           int c=q.front(),i;

           q.pop();vs[c]=false;

           for (i=head[c]; i!=-1; i=arc[i].next){

               if (dis[c]+arc[i].val<dis[arc[i].u]){

                  dis[arc[i].u]=dis[c]+arc[i].val;

                  if (!vs[arc[i].u]){

                     q.push(arc[i].u);

                     vs[arc[i].u]=true;

                  }

               }

           }

     }

     printf("%d",dis[T]);

}

void read(int &x) {

    char c;

    while((c=getchar())<'0' || c>'9');

    x=c-'0';

    while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';

}

void Input() {//读入

    for(int i=0, id1, id2, a; i<=n-1; i++)//读入相邻横边

        for(int j=1; j<=m-1; j++) {

            read(a);

            id1=((i-1)*(m-1)+j)*2-1;

            id2=(i*(m-1)+j)*2;//从1图通往2图

            if(i==0) id1=T,add_arc(id2, id1, a);

            else if(i==n-1) id2=S,add_arc(id2, id1, a);

            else add_arc(id1, id2, a),add_arc(id2, id1, a);

        }//增边

    for(int i=1, id1, id2, a; i<=n-1; i++)

        for(int j=0; j<m; j++) {

            read(a);

            id1=((i-1)*(m-1)+j)*2;

            id2=((i-1)*(m-1)+j+1)*2-1;

            if(j==0) id1=S,add_arc(id1, id2, a);

            else if(j==m-1) id2=T,add_arc(id1, id2, a);

            else add_arc(id1, id2, a),add_arc(id2, id1, a);

        }

    for(int i=1, id1, id2, a; i<=n-1; i++)

        for(int j=1; j<=m-1; j++) {

            read(a);

            id1=((i-1)*(m-1)+j)*2;

            id2=((i-1)*(m-1)+j)*2-1;

            add_arc(id1, id2, a);

            add_arc(id2, id1, a);

        }

}

int main() {

    freopen("1001.in","r",stdin);

    freopen("1001.out","w",stdout);

    read(n), read(m);//读入整数

    S=0, T=(n-1)*(m-1)*2+1;//S是源点T是汇点

    fill(head, head+T+1, -1), tot=0;//初始化为全-1

    if(n==1 || m==1) {//处理特殊情况

        if(n>m) swap(n, m);

        int ans=INF;

        for(int i=1, a; i<m; i++) {

            read(a);

            if(ans>a) ans=a;

        }

        printf("%d\n", ans==INF?0:ans);

    }

    else Input(), SPFA();

    return 0;

}

//BZOJ 1001

ps谁告诉我为什么代码片点确定没反应qwqwq
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: