HDU 1045 Fire Net
题面:给你一个不大于4*4的方格然后中间会有障碍格子,问其中能最多有多少个标记的方格,是无法直接(横竖方向上没有标记,或者被障碍挡住)达到的,看样例应该也能懂;
题解:每一个 行 对应一个 列 如果一行之中多了一个障碍物 分割了这一行那么当作新 行 来算 ,同理 列也是那么处理(这题爆搜也能过,不过和我预想练习的目的不一致就不在此解答了)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
using namespace std;
const int maxn = 1e3+10;
namespace flow {
struct edge {
int to,cap,flow,rev;
edge(int t,int c,int f,int r):to(t),cap(c),flow(f),rev(r){};
};
vector<edge>g[maxn+10];
int S,T,ndcnt,d[maxn+10],cur[maxn+10];
queue<int>q;
void init(int ss,int tt,int nn) {
S=ss;
T=tt;
for(int i=1; i<=ndcnt; i++)g[i].clear();
ndcnt=nn;
}
void addedge(int l,int r,int w) {
g[l].push_back(edge(r,w,0,(int)g[r].size()));
g[r].push_back(edge(l,0,0,(int)g[l].size()-1));
}
bool bfs() {
for(int i=1; i<=ndcnt; i++)
d[i] = i == S ? 0 : -1;
q.push(S);
while(!q.empty()) {
int p = q.front();
q.pop();
for(int i=0; i<g[p].size(); i++) {
edge e = g[p][i];
if(e.cap>e.flow && d[e.to] == -1) {
d[e.to] = d[p] + 1;
q.push(e.to);
}
}
}
return d[T] != -1;
}
int dfs(int p, int a) {
if(p==T)return a;
int ans=0,now;
for(int &i = cur[p]; i<g[p].size(); i++) {
edge &e = g[p][i];
if(e.cap>e.flow && d[p]+1 == d[e.to]) {
now = dfs(e.to,min(a,e.cap-e.flow));
e.flow+=now;
g[e.to][e.rev].flow-=now;
ans+=now;
a-=now;
if(!a)break;
}
}
return ans;
}
int solve() {
int ans=0;
while(bfs()) {
for(int i=1; i<=ndcnt; i++) {
cur[i]=0;
}
ans+=dfs(S,1e9);
}
return ans;
}
}
char mp[100][100];
int p1[100][100],p2[100][100];
int main() {
int n;
while(scanf("%d",&n)) {
if(n==0)break;
for(int i=1; i<=n; i++) {
scanf("%s",mp[i]+1);
}
flow:: init(99,100,105);
int cnt=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
p1[i][j]=cnt;
if(mp[i][j]=='X')cnt++;
}
cnt++;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
p2[j][i]=cnt;
if(mp[j][i]=='X')cnt++;
}
cnt++;
}
set<int>num1,num2;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(mp[i][j]!='X'){
flow::addedge(p1[i][j],p2[i][j],1);
//cout<<p1[i][j]<<" "<<p2[i][j]<<endl;
}
num1.insert(p1[i][j]);
num2.insert(p2[i][j]);
}
}
for(int it:num1)flow::addedge(99,it,1);
for(int it:num2)flow::addedge(it,100,1);
printf("%d\n",flow::solve());
}
return 0;
}
HDU 2444
题面:挺绕,但是读懂后就比较简单,;
就是将一群人分成两个组,这两个组中没有相互认识的人,如果不能这么分则输出No,要不然就输出这两组的最大两两认识匹配.
思路:
先用:染色法(bfs,或者,dfs)标记,判断有误冲突;
然后分类完后进行建边,然后dinic跑一遍就好了
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 10000;
namespace flow {
struct edge {
int to, cap, flow, rev;
edge() {};
edge(int a,int b,int c,int d):to(a),cap(b),flow(c),rev(d) {};
};
vector<edge> g[maxn + 10];
int s, t, ndcnt, d[maxn + 10], cur[maxn + 10];
queue<int> q;
void init(int ss, int tt, int nn) {
s = ss;
t = tt;
for (int i = 1; i <= ndcnt; ++i) g[i].clear();
ndcnt = nn;
}
void addedge(int l, int r, int w) {
g[l].push_back(edge(r, w, 0, (int)g[r].size()));
g[r].push_back(edge(l, 0, 0, (int)g[l].size() - 1));
}
bool bfs() {
for (int i = 1; i <= ndcnt; ++i)
d[i] = i == s ? 0 : -1;
q.push(s);
while (!q.empty()) {
int p = q.front();
q.pop();
for (int i = 0; i < (int)g[p].size(); ++i) {
edge e = g[p][i];
if (e.cap > e.flow && d[e.to] == -1) {
d[e.to] = d[p] + 1;
q.push(e.to);
}
}
}
return d[t] != -1;
}
int dfs(int p, int a) {
if (p == t) return a;
int ans = 0, now;
for (int &i = cur[p]; i < (int)g[p].size(); ++i) {
edge &e = g[p][i];
if (e.cap > e.flow && d[p] + 1 == d[e.to]) {
now = dfs(e.to, min(a, e.cap - e.flow));
e.flow += now;
g[e.to][e.rev].flow -= now;
ans += now;
a -= now;
if (!a) break;
}
}
return ans;
}
int solve() {
int ans = 0;
while (bfs()) {
for (int i = 1; i <= ndcnt; ++i) cur[i] = 0;
ans += dfs(s, 1e9);
}
return ans;
}
}
int n,m;
vector<int>e[maxn];
int vis[maxn];
bool check() {
for(int i=0; i<=n; i++)vis[i]=0;
int flag=0;
queue<int>q;
for(int i=1; i<=n; i++) {
q.push(i);
if(vis[i]==0)vis[i]=1;
while(!q.empty()) {
int tmp = q.front(),ff = (vis[tmp]==1?2:1);
q.pop();
for(int it:e[tmp]) {
if(vis[it]==0) {
vis[it]=ff;
q.push(it);
} else {
if(vis[tmp]==vis[it]) {
flag=1;
break;
}
}
if(flag)break;
}
if(flag)break;
}
}
return flag;
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=0; i<=n; i++)
e[i].clear();
int ta,tb;
for(int i=0; i<m; i++) {
scanf("%d%d",&ta,&tb);
e[ta].push_back(tb);
e[tb].push_back(ta);
}
if(check()) {
puts("No");
continue;
}
flow::init(201,202,250);
for(int i=0; i<=n; i++) {
if(vis[i]!=1)continue;
flow::addedge(201,i,1);
for(int it:e[i])
flow::addedge(i,it,1);
}
for(int i=0; i<=n; i++) {
if(vis[i]==2)
flow::addedge(i,202,1);
}
printf("%d\n",flow::solve());
}
return 0;
}