其他分享
首页 > 其他分享> > 网络流24题——孤岛营救(分层图最短路)

网络流24题——孤岛营救(分层图最短路)

作者:互联网

题目链接:https://loj.ac/problem/6121

解题报告:由于p很小,所以可以通过二进制表示当前是否有该点的钥匙,建完图跑最短路,其他的没什么难点了

AC代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<vector>
  5 #include<queue>
  6 #include<cstring>
  7 #include<algorithm>
  8 #define numm ch-48
  9 #define pd putchar(' ')
 10 #define pn putchar('\n')
 11 #define pb push_back
 12 #define debug(args...) cout<<#args<<"->"<<args<<endl
 13 #define bug cout<<"************"
 14 using namespace std;
 15 template <typename T>
 16 void read(T &res) {
 17     bool flag=false;char ch;
 18     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
 19     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 20     flag&&(res=-res);
 21 }
 22 template <typename T>
 23 void write(T x) {
 24     if(x<0) putchar('-'),x=-x;
 25     if(x>9) write(x/10);
 26     putchar(x%10+'0');
 27 }
 28 typedef long long ll;
 29 const int maxn=110+10;
 30 const int inf=0x3f3f3f3f;
 31 const int mod=1e9+7;
 32 struct wtz {
 33     int state,v;
 34     wtz(){}
 35     wtz(int state,int v):state(state),v(v){}
 36 };
 37 struct node {
 38     int v,net,w;
 39     node(){}
 40     node(int v,int net,int w):v(v),net(net),w(w){}
 41 }e[maxn*maxn*4];
 42 int dx[4]={1,-1,0,0};
 43 int dy[4]={0,0,1,-1};
 44 int cnt,st,ed,id[maxn][maxn],a[maxn][maxn],dis[2100][maxn],head[maxn];
 45 int key[maxn],len;
 46 void addedge(int u,int v,int w) {
 47     e[cnt]=node(v,head[u],w);
 48     head[u]=cnt++;
 49 }
 50 int spfa() {
 51     queue<wtz>que;
 52     que.push(wtz(1,st));    ///得到1号钥匙
 53     dis[1][st]=0;
 54     while(!que.empty()) {
 55         wtz now=que.front();
 56         que.pop();
 57         int u=now.v;
 58         dis[now.state|key[u]][u]=min(dis[now.state|key[u]][u],dis[now.state][u]);
 59         now.state|=key[u];   ///得到u点的钥匙
 60         for(int i=head[u];~i;i=e[i].net) {
 61             int v=e[i].v;
 62             if((now.state&e[i].w)==e[i].w) {    ///state拥有这扇门的钥匙
 63                 if(dis[now.state][v]>dis[now.state][u]+1) {
 64                     dis[now.state][v]=dis[now.state][u]+1;
 65                     que.push(wtz(now.state,v));
 66                 }
 67             }
 68         }
 69     }
 70     int ans=inf;
 71     for(int i=1;i<2100;i++)
 72         ans=min(ans,dis[i][ed]);
 73     return ans==inf?-1:ans;
 74 }
 75 int main()
 76 {
 77     int m,n,p,k;
 78     while(scanf("%d%d%d",&n,&m,&p)!=EOF) {
 79         cnt=0,st=1,ed=n*m;
 80         for(int i=1;i<=n;i++) {
 81             for(int j=1;j<=m;j++) {
 82                 id[i][j]=++cnt; ///得到点(i,j)的线性标号
 83             }
 84         }
 85         memset(dis,inf,sizeof(dis));
 86         memset(head,-1,sizeof(head));
 87         memset(a,-1,sizeof(a));
 88         memset(key,0,sizeof(key));
 89         int x1,x2,y1,y2,g;
 90         cnt=0;
 91         read(k);
 92         for(int i=1;i<=k;i++) {
 93             read(x1),read(y1),read(x2),read(y2),read(g);
 94             int u=id[x1][y1];
 95             int v=id[x2][y2];
 96             a[u][v]=a[v][u]=g;
 97             if(g) {
 98                 addedge(u,v,1<<g);
 99                 addedge(v,u,1<<g);
100             }
101         }
102         for(int i=1;i<=n;i++) {
103             for(int j=1;j<=m;j++) {
104                 int u=id[i][j];
105                 for(int k=0;k<4;k++) {
106                     int x=i+dx[k];
107                     int y=j+dy[k];
108                     if(x<1||y<1||x>n||y>m) continue;
109                     int v=id[x][y];
110                     if(a[u][v]==-1) ///u和v之间没有墙和门,也可认为是1类门
111                         addedge(u,v,1);
112                 }
113             }
114         }
115         int s;
116         read(s);
117         for(int i=1;i<=s;i++) {
118             read(x1),read(y1),read(g);
119             key[id[x1][y1]]|=(1<<g); ///每个点存放的钥匙可以有多种
120         }
121         write(spfa());pn;
122     }
123     return 0;
124 }
View Code

 

标签:24,include,int,短路,state,maxn,孤岛,now,dis
来源: https://www.cnblogs.com/wuliking/p/11586696.html