- Fire Net
这一题和下面这题差不多,都可以看看,我感觉这种建图方式很强,反正是我想不到的类型。
poj-226
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e3 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const double pi=3.141592653589;
int x,y;
int mp[2550][2550],used[2550],nex[2550],c[55][55],b[55][55];
bool dfs(int zz)
{
for(int j=1;j<=y;j++)
{
if(mp[zz][j]&&!used[j])
{
used[j]=1;
if(nex[j]==0||dfs(nex[j]))
{
nex[j]=zz;
return true;
}
}
}
return false;
}
int max_match()
{
int sum=0;
for(int i=1;i<=x;i++)
{
ms(used,0);
sum+=dfs(i);
}
return sum;
}
char s[305][305];
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==0)break;
// init();
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
}
// ms(c,0);
ms(nex,0);
ms(mp,0);
x=1;
for(int i=1;i<=n;i++)//先遍历行,x的意思是这一行可以放的标号,但是碰到X时要要x++,原因是这碰到墙后之后这一行又可以放一个新的了
{
for(int j=1;j<=n;j++)
{
if(s[i][j]=='.')
{
b[i][j]=x;
}
else if(s[i][j]=='X')
{
x++;
}
}
x++;//表示下一行也可以放新的了
}
y=1;
for(int i=1;i<=n;i++)//和行相同,只是换成列了
{
for(int j=1;j<=n;j++)
{
if(s[j][i]=='.')
{
c[j][i]=y;
}
else if(s[j][i]=='X')
{
y++;
}
}
y++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(s[i][j]=='.')
mp[b[i][j]][c[i][j]]=1;//表示b[i][j]与c[i][j]互斥的,只能从中选一个,二分图匹配后就是最大匹配数
}
}
printf("%d\n",max_match());
}
return 0;
}
- The Accomodation of Students
这一题和上题差不多,会了上一题后这题只要解决No这一种情况就好了
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e5 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const double pi=3.141592653589;
//mp[i][j]表示i与j之间连了一条边,used表示该店是否被访问,nex[i]表示这个点是否已经匹配
//二分图匹配最小顶点覆盖
int n,m;
int mp[430][430],used[maxn],nex[maxn];
bool dfs(int x)
{
for(int j=1;j<=n;j++)
{
if(mp[x][j]&&!used[j])
{
used[j]=1;
if(nex[j]==0||dfs(nex[j]))
{
nex[j]=x;
return true;
}
}
}
return false;
}
int max_match()
{
int sum=0;
for(int i=1;i<=n;i++)
{
ms(used,0);
sum+=dfs(i);
}
return sum;
}
int vis[maxn];
int main()
{
while(~scanf("%d%d",&n,&m))
{
bool flage=true;
ms(mp,0);
ms(nex,0);
ms(vis,0);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
mp[u][v]=1;
if(vis[u]!=0&&vis[u]==vis[v])//如果本来是属于一个阵营,然后突然变成了敌对阵营了,那不是有内奸?所以输出No,好好体会一下,这题就知道怎么写了
{
flage=false;
}
vis[u]=1;
vis[v]=2;
}
if(!flage)
{
printf("No\n");
continue;
}
printf("%d\n",max_match());
}
return 0;
}
- Courses HDU - 1083
这一题没啥好说的,就是个裸体,找到最大匹配数就好了,如果最大匹配数等于课程数就是YES,如果小于就NO,不会有大于这种情况。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e5 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const double pi=3.141592653589;
//mp[i][j]表示i与j之间连了一条边,used表示该店是否被访问,nex[i]表示这个点是否已经匹配
//二分图匹配最小顶点覆盖
int n,m;
int mp[430][430],used[maxn],nex[maxn];
bool dfs(int x)
{
for(int j=1;j<=m;j++)
{
if(mp[x][j]&&!used[j])
{
used[j]=1;
if(nex[j]==0||dfs(nex[j]))
{
nex[j]=x;
return true;
}
}
}
return false;
}
int max_match()
{
int sum=0;
for(int i=1;i<=n;i++)
{
ms(used,0);
sum+=dfs(i);
}
return sum;
}
//int vis[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ms(mp,0);
ms(nex,0);
scanf("%d%d",&n,&m);
int x;
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
for(int j=1;j<=k;j++)
{
scanf("%d",&x);
mp[i][x]=1;
}
}
if(max_match()==n)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}
- 棋盘游戏
在n*m的,里有k地方可以放“车”,在这里放"车"后横竖都都不能放“车”了,问最多可以放几个车,和有几个地方不放车,那么会改变车放的最大数量。
跑完匈牙利后再枚举每个点,如果车的数量变了,那么就++。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e4 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const double pi=3.141592653589;
//mp[i][j]表示i与j之间连了一条边,used表示该店是否被访问,nex[i]表示这个点是否已经匹配
//二分图匹配最小顶点覆盖
int n,m,k;
int mp[105][105],used[maxn],nex[maxn];
bool dfs(int x)
{
for(int j=1;j<=m;j++)
{
if(mp[x][j]&&!used[j])
{
used[j]=1;
if(nex[j]==0||dfs(nex[j]))
{
nex[j]=x;
return true;
}
}
}
return false;
}
int max_match()
{
int sum=0;
for(int i=1;i<=n;i++)
{
ms(used,0);
sum+=dfs(i);
}
return sum;
}
//int vis[maxn];
int main()
{
int cas=1;
while(~scanf("%d%d%d",&n,&m,&k))
{
int u,v;
ms(nex,0);
ms(mp,0);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&u,&v);
mp[u][v]=1;
}
int ans=max_match(),cnt=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j])
{
mp[i][j]=0;
ms(nex,0);//这里一定要初始化,还有数组要开小一点,不然会T,但是我看别人的代码不一样,可以去看看别人的代码。
int temp=max_match();
if(temp!=ans)
{
cnt++;
}
mp[i][j]=1;
}
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",cas++,cnt,ans);
}
return 0;
}
- Swap HDU - 2819
这一题我也不知道怎么说大家去看一下这个大佬的博客吧戳我进入
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e4 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const double pi=3.141592653589;
//mp[i][j]表示i与j之间连了一条边,used表示该店是否被访问,nex[i]表示这个点是否已经匹配
//二分图匹配最小顶点覆盖
int n;
int mp[105][105],used[maxn],nex[maxn];//,a[55][55],b[55][55];
bool dfs(int x)
{
for(int j=1;j<=n;j++)
{
if(mp[x][j]&&!used[j])
{
used[j]=1;
if(nex[j]==0||dfs(nex[j]))
{
nex[j]=x;
return true;
}
}
}
return false;
}
int max_match()
{
int sum=0;
for(int i=1;i<=n;i++)
{
ms(used,0);
sum+=dfs(i);
}
return sum;
}
vector<int>ans1,ans2;
int main()
{
while(~scanf("%d",&n))
{
ms(nex,0);
// len=0;
ans1.clear();
ans2.clear();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&mp[i][j]);
}
}
if(n!=max_match())
{
printf("-1\n");
}
else
{
int j;
for(int i=1;i<=n;i++)
{
for(j=1;j<=n&&nex[j]!=i;j++);
if(j!=i)
{
ans1.push_back(i);
ans2.push_back(j);
swap(nex[i],nex[j]);
}
}
printf("%d\n",ans1.size());
for(int i=0;i<ans1.size();i++)
{
printf("C %d %d\n",ans1[i],ans2[i]);
}
}
}
return 0;
}