zoukankan      html  css  js  c++  java
  • BZOJ2150: 部落战争

    题解:

    把每个点拆成入点和出点,因为必须经过一次且只能经过一次。所以在两个点之间连一条上界=下界=1的边。

    然后再s到每个入点连边,每个出点向t连边,点与点之间。。。

    求最小流就可以过了。。。

    (感觉最小流神一般的存在。。。)

    代码:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<iostream>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<queue>
     11 #include<string>
     12 #define inf 1000000000
     13 #define maxn 100000+5
     14 #define maxm 100000+5
     15 #define eps 1e-10
     16 #define ll long long
     17 #define pa pair<int,int>
     18 #define for0(i,n) for(int i=0;i<=(n);i++)
     19 #define for1(i,n) for(int i=1;i<=(n);i++)
     20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     22 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
     23 #define mod 1000000007
     24 using namespace std;
     25 inline int read()
     26 {
     27     int x=0,f=1;char ch=getchar();
     28     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     29     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     30     return x*f;
     31 }
     32 int  n,m,s,t,r,c,ss,tt,maxflow,tot=1,head[maxn],cur[maxn],h[maxn],in[maxn],num[100][100][2];
     33 queue<int>q;
     34 bool a[100][100];
     35 struct edge{int go,next,v;}e[maxm];
     36 inline void ins(int x,int y,int v)
     37 {
     38     e[++tot]=(edge){y,head[x],v};head[x]=tot;
     39     e[++tot]=(edge){x,head[y],0};head[y]=tot;
     40 }
     41 inline void insert(int x,int y,int l,int r)
     42 {
     43     in[y]+=l;in[x]-=l;ins(x,y,r-l);
     44 }
     45 void build()
     46 {
     47     for0(i,tt)if(in[i]>0)ins(ss,i,in[i]);else if(in[i]<0)ins(i,tt,-in[i]);
     48 }
     49 bool bfs()
     50 {
     51     for(int i=0;i<=tt;i++)h[i]=-1;
     52     q.push(s);h[s]=0;
     53     while(!q.empty())
     54     {
     55         int x=q.front();q.pop();
     56         for(int i=head[x];i;i=e[i].next)
     57          if(e[i].v&&h[e[i].go]==-1)
     58          {
     59             h[e[i].go]=h[x]+1;q.push(e[i].go);
     60          }
     61     }
     62     return h[t]!=-1;
     63 }
     64 int dfs(int x,int f)
     65 {
     66     if(x==t) return f;
     67     int tmp,used=0;
     68     for(int i=cur[x];i;i=e[i].next)
     69      if(e[i].v&&h[e[i].go]==h[x]+1)
     70     {
     71         tmp=dfs(e[i].go,min(e[i].v,f-used));
     72         e[i].v-=tmp;if(e[i].v)cur[x]=i;
     73         e[i^1].v+=tmp;used+=tmp;
     74         if(used==f)return f;       
     75     }
     76     if(!used) h[x]=-1;
     77     return used;
     78 }
     79 void dinic()
     80 {
     81     maxflow=0;
     82     while(bfs())
     83     {
     84         for (int i=0;i<=tt;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
     85     }
     86 }
     87 int minflow()
     88 {
     89     s=ss;t=tt;
     90     dinic();
     91     int ans=e[tot].v;
     92     e[tot].v=e[tot^1].v=0;
     93     s=2*n*m+1;t=0;
     94     dinic();
     95     return ans-maxflow;
     96 }
     97 int main()
     98 {
     99     freopen("input.txt","r",stdin);
    100     freopen("output.txt","w",stdout);
    101     n=read();m=read();r=read();c=read();
    102     for1(i,n)for1(j,m)
    103     {
    104       char ch=getchar();while(ch!='.'&&ch!='x')ch=getchar();
    105       a[i][j]=ch=='.';
    106     }
    107     for1(i,n)for1(j,m)num[i][j][0]=num[i][j][1]=(i-1)*m+j,num[i][j][1]+=n*m;
    108     s=0;t=2*n*m+1;ss=t+1;tt=t+2;
    109     for1(i,n)for1(j,m)if(a[i][j])
    110     {
    111         insert(s,num[i][j][0],0,1);
    112         insert(num[i][j][1],t,0,1);
    113         insert(num[i][j][0],num[i][j][1],1,1);
    114         int x,y;
    115         x=i+r;y=j+c;
    116         if(x>0&&x<=n&&y>0&&y<=m&&a[i][j])insert(num[i][j][1],num[x][y][0],0,1);
    117         x=i+r;y=j-c;
    118         if(x>0&&x<=n&&y>0&&y<=m&&a[i][j])insert(num[i][j][1],num[x][y][0],0,1);
    119         x=i+c;y=j+r;
    120         if(x>0&&x<=n&&y>0&&y<=m&&a[i][j])insert(num[i][j][1],num[x][y][0],0,1);
    121         x=i+c;y=j-r;
    122         if(x>0&&x<=n&&y>0&&y<=m&&a[i][j])insert(num[i][j][1],num[x][y][0],0,1);
    123     }
    124     build();
    125     insert(t,s,0,inf);
    126     printf("%d
    ",minflow());    
    127     return 0;
    128 }
    View Code

    2150: 部落战争

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 354  Solved: 218
    [Submit][Status]

    Description

    lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。 A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。 3. 每支军队都可以在任意一个城镇停止征战。 4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。 lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

    Input

    第一行包含4个整数M、N、R、C,意义见问题描述。接下来M行每行一个长度为N的字符串。如果某个字符是'.',表示这个地方是城镇;如果这个字符时'x',表示这个地方是高山深涧。

    Output

    输出一个整数,表示最少的军队个数。

    Sample Input

    【样例输入一】
    3 3 1 2
    ...
    .x.
    ...
    【样例输入二】
    5 4 1 1
    ....
    ..x.
    ...x
    ....
    x...

    Sample Output

    【样例输出一】
    4

    【样例输出二】
    5
    【样例说明】

    【数据范围】
    100%的数据中,1<=M,N<=50,1<=R,C<=10。
  • 相关阅读:
    English,The Da Vinci Code, Chapter 23
    python,meatobject
    English,The Da Vinci Code, Chapter 22
    English,The Da Vinci Code, Chapter 21
    English,The Da Vinci Code, Chapter 20
    English,The Da Vinci Code, Chapter 19
    python,xml,ELement Tree
    English,The Da Vinci Code, Chapter 18
    English,The Da Vinci Code, Chapter 17
    English,The Da Vinci Code, Chapter 16
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4177008.html
Copyright © 2011-2022 走看看