网络流24题——孤岛营救问题(状压+分层图)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4845

分析:其实可以直接bfs或者ida*的。。就是无解的时候不太好搞。。

首先钥匙数<=10,可以状压一下,然后共不超过2^10总状态,每种状态下搞一个图,把不同状态的图通过有钥匙的点连接起来,把终点全部连起来,然后搞一下最短路径即可。注意hdu上的多组数据。。因为这个wa了好几发。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<stack>
  6 #include<queue>
  7 using namespace std;
  8 const int maxn=16,maxstatus=1<<10,inf=1e9;
  9 int n,m,p,k;
 10 void Swap(int &a,int &b){int t=a;a=b;b=t;}
 11 bool wall[maxn*maxn][maxn*maxn];
 12 int dis[maxstatus*maxn*maxn+maxn*maxn+1];
 13 bool inq[maxstatus*maxn*maxn+maxn*maxn+1];
 14 struct door{
 15     int x,y;
 16     door(int x,int y){this->x=x;this->y=y;}
 17 };
 18 struct Edge{
 19     int to,dis;
 20     Edge (int to,int dis){
 21         this->to=to;this->dis=dis;
 22     }
 23 };
 24 vector<Edge> G[maxstatus*maxn*maxn+maxn*maxn+1];
 25 vector<door> d[15];
 26 void add(int s,int t,int dis){
 27     G[s].push_back(Edge(t,dis));
 28     G[t].push_back(Edge(s,dis));
 29 }
 30 void build(){
 31     for(int status=0;status<(1<<p);status++){
 32         int delta=status*maxn*maxn;
 33         for(int i=1;i<=n;i++){
 34             for(int j=1;j<=m;j++){
 35                 int x=maxn*i+j,y;
 36                 if(j<m){
 37                     y=maxn*i+j+1;
 38                     if(!wall[x][y])add(delta+x,delta+y,1);
 39                 }
 40                 if(i<n){
 41                     y=maxn*(i+1)+j;
 42                     if(!wall[x][y])add(delta+x,delta+y,1);
 43                 }
 44             }
 45         }
 46         for(int i=1;i<=p;i++){
 47             if(((1<<(i-1))&status)==0)continue;
 48             for(int j=0;j<d[i].size();j++){
 49                 add(delta+d[i][j].x,delta+d[i][j].y,1);
 50             }
 51         }
 52     }
 53     for(int i=0;i<(1<<p)-1;i++){
 54         //add(i*maxn*maxn+maxn+1,(i+1)*maxn*maxn+maxn+1,0);
 55         add(i*maxn*maxn+n*maxn+m,(i+1)*maxn*maxn+n*maxn+m,0);
 56     }
 57 }
 58 int spfa(){
 59     int s=maxn+1,t=maxn*n+m;
 60     for(int i=0;i<=maxstatus*maxn*maxn+maxn*maxn;i++)dis[i]=inf;
 61     memset(inq,0,sizeof(inq));
 62     queue<int> Q;
 63     Q.push(s);
 64     inq[s]=true;
 65     dis[s]=0;
 66     while(!Q.empty()){
 67         int x=Q.front();Q.pop();
 68         inq[x]=false;
 69         for(int i=0;i<G[x].size();i++){
 70             int to=G[x][i].to;
 71             if(dis[to]>dis[x]+G[x][i].dis){
 72                 dis[to]=dis[x]+G[x][i].dis;
 73                 if(!inq[to]){
 74                     Q.push(to);inq[to];
 75                 }
 76             }
 77         }
 78     }
 79     if(dis[t]==inf)return -1;
 80     return dis[t];
 81 }
 82 int main(){
 83 //    freopen("e:\in.txt","r",stdin);
 84     while(scanf("%d%d%d",&n,&m,&p)!=EOF){
 85         for(int i=0;i<15;i++)d[i].clear();
 86         for(int i=0;i<=(1<<p)*maxn*maxn+maxn*maxn;i++)G[i].clear();
 87         memset(wall,0,sizeof(wall));
 88         int k,x1,y1,x2,y2,g,s;
 89         scanf("%d",&k);
 90         for(int i=0;i<k;i++){
 91             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
 92             int u=x1*maxn+y1,t=x2*maxn+y2;
 93             if(u>t)Swap(u,t);
 94             wall[u][t]=true;
 95             if(g){
 96                 d[g].push_back(door(u,t));
 97             }
 98         }
 99         scanf("%d",&s);
100         while(s--){
101             scanf("%d%d%d",&x1,&y1,&g);
102             int t=1<<(g-1);
103             for(int i=0;i<(1<<p);i++){
104                 if(i>(i^t))continue;
105                 add(i*maxn*maxn+x1*maxn+y1,(i^t)*maxn*maxn+x1*maxn+y1,0);
106             }
107         }
108         build();
109         printf("%d
",spfa());
110     }
111     return 0;
112 }
原文地址:https://www.cnblogs.com/7391-KID/p/7478926.html