您的位置:首页 > 其它

HDU 3605 Escape

2015-08-21 10:47 316 查看
状态压缩+最大流

因为最多只有10个星球,所以人最多只有1<<10种。所以按照人的种类来建图。

此题有毒,光是输入就TLE了,联系了HDU OJ管理员胡杰,把时间放宽为2000ms,最终,用了输入挂,用了C++提交,1200ms过了;不用输入挂 用C++ 1700ms。



#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn = 1500 + 10;
const int INF = 0x7FFFFFFF;

struct Edge
{
int from, to, cap, flow;
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int n, m, s, t;

int Scan()
{
int res = 0, ch, flag = 0;

if ((ch = getchar()) == '-')             //判断正负
flag = 1;

else if (ch >= '0' && ch <= '9')           //得到完整的数
res = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9')
res = res * 10 + ch - '0';

return flag ? -res : res;
}

//求出层次网络
bool BFS()
{
memset(vis, 0, sizeof(vis));
queue<int>Q;
Q.push(s);
d[s] = 0;
vis[s] = 1;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = 0; i<G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}

//加边
void AddEdge(int from, int to, int cap)
{
Edge r;
r.from = from;
r.to = to;
r.cap = cap;
r.flow = 0;
edges.push_back(r);
Edge d;
d.from = to;
d.to = from;
d.cap = 0;
d.flow = 0;
edges.push_back(d);
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}

//每个阶段来一次DFS增广
int DFS(int x, int a)
{
if (x == t || a == 0) return a;
int flow = 0, f;
for (int i = cur[x]; i<G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0)
{
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}

//多个阶段,多次建立层次网络。
int Maxflow(int ss, int tt)
{
int flow = 0;
while (BFS())
{
memset(cur, 0, sizeof(cur));
flow += DFS(ss, INF);
}
return flow;
}

int N, M;
int Tot[maxn];
int Er[maxn];
int zh[maxn];
int ZH[maxn];

int main()
{
while (scanf("%d%d", &N, &M) != EOF)
{
edges.clear();
for (int i = 0; i<maxn; i++) G[i].clear();
memset(Tot, 0, sizeof Tot);

for (int i = 1; i <= N; i++)
{
int Ans = 0;
for (int j = 0; j < M; j++) Er[j] = Scan();
for (int j = 0; j<M; j++) Ans = Ans + Er[j] * pow(2.0,j);
Tot[Ans]++;
}
s = 1401;
t = 1400;
for (int i = 0; i <= (1<<10); i++)
{
if (Tot[i])
{
AddEdge(s, i, Tot[i]);
int y = i, q = 0, d = 0;
while (y) zh[q] = y % 2, y = y / 2, q++;
for (int ii = 0; ii<q; ii++)
if (zh[ii])
AddEdge(i, 1100 + ii, INF);
}
}
for (int i = 0; i<M; i++)
{
int x;
x = Scan();
AddEdge(1100 + i, t, x);
}
int FF = Maxflow(s, t);
if (FF != N) printf("NO\n");
else printf("YES\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: