zoukankan      html  css  js  c++  java
  • 网络流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('
    ')
     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
  • 相关阅读:
    Shell是linux下的脚本语言解析器
    semver 是 语义化版本
    js中限制字符串输入中英文字符的长度封装
    chalk.js(node终端样式库)
    分页
    利用Nodejs的os.networkInterfaces()模块修改vuecli项目默认打开地址
    物理像素
    长列表优化eg
    [JSOI2008]球形空间产生器
    标记不下传线段树(混蛋树)
  • 原文地址:https://www.cnblogs.com/wuliking/p/11586696.html
Copyright © 2011-2022 走看看