hdu3472(混合图欧拉路径判断)
2016-06-14 20:38
363 查看
链接:点击打开链接
题意:有n个单词,有的可以前后颠倒,看是否可以将n个单词首尾相连
代码:#include <set>
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;
struct node{
int u,v,cap;
node(){}
node(int u,int v,int cap):u(u),v(v),cap(cap){}
}es[1005*1005];
int R,S,T;
int dis[1005],deg[1005],iter[1005];
vector<int> tab[1005];
void addedge(int u, int v, int cap){
tab[u].push_back(R);
es[R++]=node(u,v,cap);
tab[v].push_back(R);
es[R++]=node(v,u,0);
}
int bfs(){
int i,h;
queue<int> q;
q.push(S);
memset(dis,INF,sizeof(dis));
dis[S]=0;
while(q.size()){
h=q.front();
q.pop();
for(i=0;i<tab[h].size();i++){
node &e=es[tab[h][i]];
if(e.cap>0&&dis[e.v]==INF){
dis[e.v]=dis[h]+1;
q.push(e.v);
}
}
}
return dis[T]<INF;
}
int dfs(int x,int maxflow){
int flow;
if(x==T)
return maxflow;
for(int &i=iter[x];i<tab[x].size();i++){
node &e=es[tab[x][i]];
if(dis[e.v]==dis[x]+1&&e.cap>0){
flow=dfs(e.v,min(maxflow,e.cap));
if(flow){
e.cap-=flow;
es[tab[x][i]^1].cap+=flow;
return flow;
}
}
}
return 0;
}
int dinic(){
int ans,flow;
ans=0;
while(bfs()){
memset(iter,0,sizeof(iter));
while(flow=dfs(S,INF))
ans+=flow;
}
return ans;
}
int par[1005],sign[50];
void init(int n){
int i;
for(i=0;i<=n;i++)
par[i]=i;
}
int found(int x){
if(par[x]==x)
return par[x];
return par[x]=found(par[x]);
}
void unite(int x,int y){
x=found(x);
y=found(y);
if(x==y)
return;
par[x]=y;
}
bool same(int x,int y){
return found(x)==found(y);
}
bool judge(){
int i,j;
for(i=1;i<=26;i++)
for(j=i+1;j<=26;j++)
if(sign[i]&&sign[j]&&(same(i,j)==0))
return 0;
return 1;
}
int main(){ //http://yzmduncan.iteye.com/blog/1149049
int n,i,j,t,c1,c2,st,en,cas,num,sum; //这个讲的很详细
char s[55];
scanf("%d",&t);
for(cas=1;cas<=t;cas++){
scanf("%d",&n);
R=S=0,T=27;
init(26);
for(i=0;i<=T;i++)
tab[i].clear();
memset(deg,0,sizeof(deg));
memset(sign,0,sizeof(sign));
for(i=0;i<n;i++){
scanf("%s%d",s,&num);
c1=s[0]-'a'+1;
c2=s[strlen(s)-1]-'a'+1;
deg[c1]--,deg[c2]++;
sign[c1]=sign[c2]=1;
if(num)
addedge(c1,c2,1);
unite(c1,c2);
}
if(judge()==0){ //并查集判断图是否联通
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
st=en=-1;
for(i=1;i<=26;i++){ //如果是存在欧拉路径而不是欧拉回路
if(deg[i]%2==1||deg[i]%2==-1){ //找出起点和终点并变成欧拉回路
if(deg[i]%2==1)
en=i;
else
st=i;
sum++;
}
}
if(sum==0||(sum==2&&st!=-1&&en!=-1))
addedge(en,st,1);
else{
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
for(i=1;i<=26;i++){ //因为每跑一条无向边两边的值相当于减2
if(deg[i]<0){ //因此与源点汇点相连的点的值除二
sum+=(-deg[i]/2);
addedge(S,i,-deg[i]/2);
}
else if(deg[i]>0)
addedge(i,T,deg[i]/2);
}
if(sum==dinic())
printf("Case %d: Well done!\n",cas);
else
printf("Case %d: Poor boy!\n",cas);
}
return 0;
}
题意:有n个单词,有的可以前后颠倒,看是否可以将n个单词首尾相连
代码:#include <set>
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;
struct node{
int u,v,cap;
node(){}
node(int u,int v,int cap):u(u),v(v),cap(cap){}
}es[1005*1005];
int R,S,T;
int dis[1005],deg[1005],iter[1005];
vector<int> tab[1005];
void addedge(int u, int v, int cap){
tab[u].push_back(R);
es[R++]=node(u,v,cap);
tab[v].push_back(R);
es[R++]=node(v,u,0);
}
int bfs(){
int i,h;
queue<int> q;
q.push(S);
memset(dis,INF,sizeof(dis));
dis[S]=0;
while(q.size()){
h=q.front();
q.pop();
for(i=0;i<tab[h].size();i++){
node &e=es[tab[h][i]];
if(e.cap>0&&dis[e.v]==INF){
dis[e.v]=dis[h]+1;
q.push(e.v);
}
}
}
return dis[T]<INF;
}
int dfs(int x,int maxflow){
int flow;
if(x==T)
return maxflow;
for(int &i=iter[x];i<tab[x].size();i++){
node &e=es[tab[x][i]];
if(dis[e.v]==dis[x]+1&&e.cap>0){
flow=dfs(e.v,min(maxflow,e.cap));
if(flow){
e.cap-=flow;
es[tab[x][i]^1].cap+=flow;
return flow;
}
}
}
return 0;
}
int dinic(){
int ans,flow;
ans=0;
while(bfs()){
memset(iter,0,sizeof(iter));
while(flow=dfs(S,INF))
ans+=flow;
}
return ans;
}
int par[1005],sign[50];
void init(int n){
int i;
for(i=0;i<=n;i++)
par[i]=i;
}
int found(int x){
if(par[x]==x)
return par[x];
return par[x]=found(par[x]);
}
void unite(int x,int y){
x=found(x);
y=found(y);
if(x==y)
return;
par[x]=y;
}
bool same(int x,int y){
return found(x)==found(y);
}
bool judge(){
int i,j;
for(i=1;i<=26;i++)
for(j=i+1;j<=26;j++)
if(sign[i]&&sign[j]&&(same(i,j)==0))
return 0;
return 1;
}
int main(){ //http://yzmduncan.iteye.com/blog/1149049
int n,i,j,t,c1,c2,st,en,cas,num,sum; //这个讲的很详细
char s[55];
scanf("%d",&t);
for(cas=1;cas<=t;cas++){
scanf("%d",&n);
R=S=0,T=27;
init(26);
for(i=0;i<=T;i++)
tab[i].clear();
memset(deg,0,sizeof(deg));
memset(sign,0,sizeof(sign));
for(i=0;i<n;i++){
scanf("%s%d",s,&num);
c1=s[0]-'a'+1;
c2=s[strlen(s)-1]-'a'+1;
deg[c1]--,deg[c2]++;
sign[c1]=sign[c2]=1;
if(num)
addedge(c1,c2,1);
unite(c1,c2);
}
if(judge()==0){ //并查集判断图是否联通
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
st=en=-1;
for(i=1;i<=26;i++){ //如果是存在欧拉路径而不是欧拉回路
if(deg[i]%2==1||deg[i]%2==-1){ //找出起点和终点并变成欧拉回路
if(deg[i]%2==1)
en=i;
else
st=i;
sum++;
}
}
if(sum==0||(sum==2&&st!=-1&&en!=-1))
addedge(en,st,1);
else{
printf("Case %d: Poor boy!\n",cas);
continue;
}
sum=0;
for(i=1;i<=26;i++){ //因为每跑一条无向边两边的值相当于减2
if(deg[i]<0){ //因此与源点汇点相连的点的值除二
sum+=(-deg[i]/2);
addedge(S,i,-deg[i]/2);
}
else if(deg[i]>0)
addedge(i,T,deg[i]/2);
}
if(sum==dinic())
printf("Case %d: Well done!\n",cas);
else
printf("Case %d: Poor boy!\n",cas);
}
return 0;
}
相关文章推荐
- 黑名单
- 使用JDBC调用mysql存储过程
- Java数据结构之简单的链表的实现
- Struts2下载文件时的Action的配置
- imx6q 修改开机LOGO指南
- windows浏览器访问linux下hadoop文件块
- linux下挂载windows目录
- [bzoj2119]股市的预测
- C指针笔记
- NOI模拟 热身赛T1
- css里面鼠标的形状-----》easyui哪点事
- ORM DAO MVC POJO
- linux 安装nginx(亲测)
- 新生活开始了
- android studio中编译问题
- Android权限【大全】
- Android Studio导入framework.jar等系统jar包方式
- 19乐学成语
- 数据库事务,课上代码
- Deep Learning(深度学习)学习笔记整理系列之(七)Convolutional Neural Networks卷积神经网络