您的位置:首页 > 其它

[平面图 贪心 || 最大流] BZOJ 2939 [Poi2000]滑雪 Skiers

2016-12-18 13:06 302 查看
直接做最大流是可以的。

不过可以发现,因为所有的路线不相交,故最左的路线尽量往左取显然是最优的。从左至右深搜此图即可得出答案。

and the following k integers are their numbers, which are ordered according to the arrangement
of glades leading to them, in east to west direction. 

这个题目弄出来的图真是interesting 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=10005;
const int M=1000005;

struct edge{
int u,v,next;
}G[M];
int head
,inum;

inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}

int n;
int tag
,vst[M];
#define V G[p].v
inline bool dfs(int u){
if (u==n) return 1;
tag[u]=1;
for (int p=head[u];p;p=G[p].next)
if (!tag[V] && !vst[p]){
vst[p]=1;
int d=dfs(V);
if (d) return 1;
}
return 0;
}

int main(){
int x,k;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<n;i++){
read(k);
for (int j=1;j<=k;j++)
read(x),add(i,x,++inum);
}
int Ans=0;
while (dfs(1))
Ans++;
printf("%d\n",Ans);
return 0;
}


无脑网络流

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

#define V G[p].v

namespace DINIC{
const int N=10005;
const int M=1000005;
struct edge{
int u,v,f,next;
}G[M<<1];
int head
,inum=1;
inline void add(int u,int v,int f,int p){
G[p].u=u; G[p].v=v; G[p].f=f; G[p].next=head[u]; head[u]=p;
}
inline void link(int u,int v,int f){
add(u,v,f,++inum); add(v,u,0,++inum);
}
inline void clear(){
cl(head); inum=1;
}
int S,T;
int Q
,l,r;
int dis
;
inline bool bfs(){
memset(dis,-1,sizeof(dis)); dis[S]=1;
l=r=-1; Q[++r]=S;
while (l<r){
int u=Q[++l];
for (int p=head[u];p;p=G[p].next)
if (G[p].f && dis[V]==-1){
dis[V]=dis[u]+1,Q[++r]=V;
if (V==T) return 1;
}
}
return 0;
}
int cur
;
inline int dfs(int u,int flow){
if (u==T) return flow;
int used=0,now;
for (int p=cur[u];p;p=G[p].next){
cur[u]=p;
if (G[p].f && dis[V]==dis[u]+1){
now=dfs(V,min(G[p].f,flow-used));
G[p].f-=now; G[p^1].f+=now;
used+=now; if (flow==used) break;
}
}
if (!used) dis[u]=-1;
return used;
}
inline int Dinic(){
int ret=0;
while (bfs()) memcpy(cur,head,sizeof(head)),ret+=dfs(S,1<<30);
return ret;
}
}

int n;

int main(){
int k,x;
using namespace DINIC;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); S=1; T=n<<1;
for (int i=1;i<n;i++){
read(k);
for (int j=1;j<=k;j++)
read(x),link(i<<1,(x<<1)-1,1);
}
for (int i=2;i<n;i++)
link((i<<1)-1,i<<1,1);
link(1,2,1<<30); link(2*n-1,n<<1,1<<30);
int Ans=Dinic();
printf("%d\n",Ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: