拆点,假设 T 时间可以完全撤离,那么每个点就拆成2*T个点,为什么是2*T个点呢?因为在两点间还要有一个流量的限制,所以个数变成T的两倍。点和点之间的容量限制很原始,因为每位置最多只能有一个人,所以正向流量是1,因为时间是正向流动的,所以逆向容量是0.
最后根据实验,这题的答案不会超过50。亏哥还用了个二分搜索加dinic,早知道直接用ek加暴力枚举,更快更好写!!!如果不是最大流就增加一层,这样的话复杂度最多50*E ,100ms之内估计就能搞定~
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
#ifdef _WIN32
#define i64 __int64
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
#define i64 long long
#define out64 "%lld\n"
#define in64 "%lld"
#endif
#define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a) for( int i = (a)-1 ; i >= 0 ; i --)
#define S64(a) scanf(in64,&a)
#define SS(a) scanf("%d",&a)
#define LL(a) ((a)<<1)
#define RR(a) (((a)<<1)+1)
#define SZ(a) ((int)a.size())
#define PP(n,m,a) puts("---");FF(i,n){FF(j,m)cout << a[i][j] << ' ';puts("");}
#define pb push_back
#define CL(Q) while(!Q.empty())Q.pop()
#define MM(name,what) memset(name,what,sizeof(name))
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-8;
const double pi = acos(-1.0);
const int maxn = 256 * 50 * 2 + 1;
const int end = 256 * 50 *2;
const int ac = 256;
const int dir[5][2]={{0,0},{1,0},{0,1},{-1,0},{0,-1}};
struct zz
{
int c;
int from;
int to;
int id;
}zx,tz;
vector<zz>g[maxn];
queue<int>q;
int cen[maxn];
bool vis[20][20];
int n,m,total;
char cs[20][20];
bool yes(int x,int y)
{
if(1<=x && x<=n && 1<=y && y<=m)
{
return true;
}
return false;
}
inline int num(int x , int y , int xx = 0)
{
return (x-1)*16 + y + ac * xx;
}
int dx(int xx)
{
return (((xx-1) % ac + 1)-1) / 16 + 1;
}
int dy(int xx)
{
return (((xx-1) % ac + 1)-1) % 16 + 1;
}
int dn(int xx)
{
return (xx - 1) / ac + 1;
}
void build(int t)
{
FF(i,maxn)
{
g[i].clear();
}
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j]=='X')
{
zx.from = 0;
zx.to = num(i,j);
zx.id = g[zx.to].size();
zx.c =1;
g[0].pb ( zx );
swap(zx.from,zx.to);
zx.id = g[0].size() - 1;
zx.c = 0;
g[zx.from].pb(zx);
}
}
int nowx,nowy;
int from,to;
FOR(k,1,t)
{
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j] == '#')
{
continue;
}
from = num(i,j, 2*k - 2);
FF(e,5)
{
nowx = i + dir[e][0];
nowy = j + dir[e][1];
if(!yes(nowx,nowy))
{
continue;
}
to = num(nowx,nowy,2*k-1);
if(cs[nowx][nowy] != '#')
{
zx.from = from;
zx.to = to;
zx.c = 1;
zx.id = g[to].size();
g[from].pb(zx);
swap(zx.from,zx.to);
zx.c = 0;
zx.id = g[from].size()-1;
g[to].pb(zx);
}
}
from = num(i,j,2*k - 1);
to = num(i,j,2*k);
zx.from = from;
zx.to = to;
zx.id = g[to].size();
zx.c=1;
g[from].pb(zx);
swap(zx.from,zx.to);
zx.c = 0;
zx.id = g[from].size() - 1;
g[to].pb(zx);
if(cs[i][j] == '@')
{
zx.from = to;
zx.to = end;
zx.id = g[end].size();
zx.c = 1;
g[zx.from].pb(zx);
swap(zx.from,zx.to);
zx.c=0;
zx.id=g[to].size()-1;
g[zx.from].pb(zx);
}
}
}
return ;
}
bool bfs0()
{
CL(q);
MM(vis,false);
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j]=='@')
{
q.push(num(i,j));
vis[i][j] = true;
}
}
int nowx,nowy,now;
while(!q.empty())
{
now = q.front();
q.pop();
FOR(i,1,4)
{
nowx = dx(now) + dir[i][0];
nowy = dy(now) + dir[i][1];
if(cs[nowx][nowy] != '#' && !vis[nowx][nowy] && yes(nowx,nowy))
{
q.push(num(nowx,nowy));
vis[nowx][nowy] = true;
}
}
}
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j] == 'X' && vis[i][j] == false)
{
return false;
}
}
return true;
}
bool bfs()
{
CL(q);
MM(cen,-1);
q.push(0);
cen[0]=0;
int now,to;
while(!q.empty())
{
now = q.front();
q.pop();
FF(i,g[now].size())
{
to = g[now][i].to;
if(g[now][i].c > 0 && cen[to] == -1)
{
cen[to] = cen[now] + 1;
q.push(to);
}
}
}
return cen[end] != -1;
}
int dfs(int flow = inf , int now = 0)
{
if(now == end)
{
return flow;
}
int temp,sum=0;
int to;
FF(i,g[now].size())
{
to = g[now][i].to;
if(cen[to] == cen[now] + 1 && flow > sum && g[now][i].c >0 )
{
temp = dfs ( min ( g[now][i].c , flow - sum ) , to );
sum += temp;
g[now][i].c -= temp;
g[to][g[now][i].id].c += temp;
}
}
if(!sum) cen[now] = -1;
return sum;
}
bool dinic()
{
int ans=0;
while(bfs())
{
ans += dfs();
}
if(ans == total)
{
return true;
}
return false;
}
int bin(int l=1,int r=50)
{
if( !bfs0 () )
{
return -1;
}
int mid;
while(l<r)
{
mid = (l+r)/2;
build(mid);
if(dinic())
{
r = mid;
}
else
{
l = mid + 1;
}
}
return l;
}
int main()
{
while(cin>>n>>m)
{
total = 0;
FOR(i,1,n) FOR(j,1,m)
{
cin>>cs[i][j];
if(cs[i][j]=='X')
{
total++;
}
}
cout<<bin()<<endl;
}
return 0;
}
稍微改了一下,在当前的剩余图中继续增加流量,140ms
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<cmath>
#include<cassert>
#include<cstring>
#include<iomanip>
using namespace std;
#ifdef _WIN32
#define i64 __int64
#define out64 "%I64d\n"
#define in64 "%I64d"
#else
#define i64 long long
#define out64 "%lld\n"
#define in64 "%lld"
#endif
#define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++)
#define FF(i,a) for( int i = 0 ; i < (a) ; i ++)
#define FFD(i,a) for( int i = (a)-1 ; i >= 0 ; i --)
#define S64(a) scanf(in64,&a)
#define SS(a) scanf("%d",&a)
#define LL(a) ((a)<<1)
#define RR(a) (((a)<<1)+1)
#define SZ(a) ((int)a.size())
#define PP(n,m,a) puts("---");FF(i,n){FF(j,m)cout << a[i][j] << ' ';puts("");}
#define pb push_back
#define CL(Q) while(!Q.empty())Q.pop()
#define MM(name,what) memset(name,what,sizeof(name))
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
const int inf = 0x3f3f3f3f;
const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL;
const double oo = 10e9;
const double eps = 10e-8;
const double pi = acos(-1.0);
const int maxn = 256 * 50 * 2 + 1;
const int end = 256 * 50 *2;
const int ac = 256;
const int dir[5][2]={{0,0},{1,0},{0,1},{-1,0},{0,-1}};
struct zz
{
int c;
int from;
int to;
int id;
}zx,tz;
vector<zz>g[maxn];
queue<int>q;
int cen[maxn];
bool vis[20][20];
int n,m,total,ans;
char cs[20][20];
bool yes(int x,int y)
{
if(1<=x && x<=n && 1<=y && y<=m)
{
return true;
}
return false;
}
inline int num(int x , int y , int xx = 0)
{
return (x-1)*16 + y + ac * xx;
}
int dx(int xx)
{
return (((xx-1) % ac + 1)-1) / 16 + 1;
}
int dy(int xx)
{
return (((xx-1) % ac + 1)-1) % 16 + 1;
}
int dn(int xx)
{
return (xx - 1) / ac + 1;
}
void build()
{
FF(i,maxn)
{
g[i].clear();
}
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j]=='X')
{
zx.from = 0;
zx.to = num(i,j);
zx.id = g[zx.to].size();
zx.c =1;
g[0].pb ( zx );
swap(zx.from,zx.to);
zx.id = g[0].size() - 1;
zx.c = 0;
g[zx.from].pb(zx);
}
}
return ;
}
void add(int t)
{
int nowx,nowy;
int from,to;
FOR(k,t,t)
{
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j] == '#')
{
continue;
}
from = num(i,j, 2*k - 2);
FF(e,5)
{
nowx = i + dir[e][0];
nowy = j + dir[e][1];
if(!yes(nowx,nowy))
{
continue;
}
to = num(nowx,nowy,2*k-1);
if(cs[nowx][nowy] != '#')
{
zx.from = from;
zx.to = to;
zx.c = 1;
zx.id = g[to].size();
g[from].pb(zx);
swap(zx.from,zx.to);
zx.c = 0;
zx.id = g[from].size()-1;
g[to].pb(zx);
}
}
from = num(i,j,2*k - 1);
to = num(i,j,2*k);
zx.from = from;
zx.to = to;
zx.id = g[to].size();
zx.c=1;
g[from].pb(zx);
swap(zx.from,zx.to);
zx.c = 0;
zx.id = g[from].size() - 1;
g[to].pb(zx);
if(cs[i][j] == '@')
{
zx.from = to;
zx.to = end;
zx.id = g[end].size();
zx.c = 1;
g[zx.from].pb(zx);
swap(zx.from,zx.to);
zx.c=0;
zx.id=g[to].size()-1;
g[zx.from].pb(zx);
}
}
}
}
bool bfs0()
{
CL(q);
MM(vis,false);
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j]=='@')
{
q.push(num(i,j));
vis[i][j] = true;
}
}
int nowx,nowy,now;
while(!q.empty())
{
now = q.front();
q.pop();
FOR(i,1,4)
{
nowx = dx(now) + dir[i][0];
nowy = dy(now) + dir[i][1];
if(cs[nowx][nowy] != '#' && !vis[nowx][nowy] && yes(nowx,nowy))
{
q.push(num(nowx,nowy));
vis[nowx][nowy] = true;
}
}
}
FOR(i,1,n) FOR(j,1,m)
{
if(cs[i][j] == 'X' && vis[i][j] == false)
{
return false;
}
}
return true;
}
bool bfs()
{
CL(q);
MM(cen,-1);
q.push(0);
cen[0]=0;
int now,to;
while(!q.empty())
{
now = q.front();
q.pop();
FF(i,g[now].size())
{
to = g[now][i].to;
if(g[now][i].c > 0 && cen[to] == -1)
{
cen[to] = cen[now] + 1;
q.push(to);
}
}
}
return cen[end] != -1;
}
int dfs(int flow = inf , int now = 0)
{
if(now == end)
{
return flow;
}
int temp,sum=0;
int to;
FF(i,g[now].size())
{
to = g[now][i].to;
if(cen[to] == cen[now] + 1 && flow > sum && g[now][i].c >0 )
{
temp = dfs ( min ( g[now][i].c , flow - sum ) , to );
sum += temp;
g[now][i].c -= temp;
g[to][g[now][i].id].c += temp;
}
}
if(!sum) cen[now] = -1;
return sum;
}
bool dinic()
{
while(bfs())
{
ans += dfs();
}
if(ans == total)
{
return true;
}
return false;
}
int bin()
{
ans=0;
if( !bfs0 () )
{
return -1;
}
build();
for(int tt=1;;tt++)
{
add(tt);
if(dinic())
{
return tt;
}
}
}
int main()
{
while(cin>>n>>m)
{
total = 0;
FOR(i,1,n) FOR(j,1,m)
{
cin>>cs[i][j];
if(cs[i][j]=='X')
{
total++;
}
}
cout<<bin()<<endl;
}
return 0;
}