BZOJ 3504 危桥

一定注意inf要开的非常大。要不然。。。嘿嘿嘿。

因为流量可能有交叉,那么要b1,b2进行交换再来跑一次。

1A很爽。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxv 650
#define maxe 250500
#define inf 9999999999999999
using namespace std;
struct edge
{
    long long v,f,nxt;
}e[maxe];
long long g[maxv],n,a1,a2,an,b1,b2,bn,nume=1,map[55][55],s,t,flag;
long long dis[maxv];
queue <long long> q;
bool vis[maxv];
char ss[55];
void addedge(long long u,long long v,long long f)
{
    e[++nume].v=v;
    e[nume].f=f;
    e[nume].nxt=g[u];
    g[u]=nume;
    e[++nume].v=u;
    e[nume].f=0;
    e[nume].nxt=g[v];
    g[v]=nume;
}
void build(long long type)
{
    memset(g,0,sizeof(g));
    nume=1;
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=n;j++)
            if (map[i][j]==1) addedge(i,j,2);
            else if (map[i][j]==2) addedge(i,j,inf);
    addedge(s,a1,2*an);addedge(a2,t,2*an);
    if (type==1) {addedge(s,b1,2*bn);addedge(b2,t,2*bn);}
    else {addedge(s,b2,2*bn);addedge(b1,t,2*bn);}
}
bool bfs()
{
    while (!q.empty()) q.pop();
    fill(dis+1,dis+t+1,-1);
    memset(vis,false,sizeof(vis));
    q.push(s);dis[s]=0;vis[s]=true;
    while (!q.empty())
    {
        long long head=q.front();
        q.pop();
        for (long long i=g[head];i;i=e[i].nxt)
        {
            long long v=e[i].v;
            if ((e[i].f) && (vis[v]==false))
            {
                dis[v]=dis[head]+1;
                vis[v]=true;
                q.push(v);
            }
        }
    }
    if (dis[t]==-1) return false;
    return true;
}
long long dinic(long long x,long long low)
{
    if (x==t) return low;
    else
    {
        long long ret=0;
        for (long long i=g[x];i;i=e[i].nxt)
        {
            long long v=e[i].v;
            if ((e[i].f) && (dis[v]==dis[x]+1))
            {
                long long dd=dinic(v,min(low,e[i].f));
                e[i].f-=dd;e[i^1].f+=dd;
                ret+=dd;low-=dd;
            }
        }
        if (ret==0) dis[x]=-1;
        return ret;
    }
}
void work(long long type)
{
    long long ret=0;
    build(type);
    while (bfs())
        ret+=dinic(s,inf);
    if (ret==an*2+bn*2) flag=1;
    else flag=0;
}
int main()
{
    while (scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF)
    {
        a1++;a2++;b1++;b2++;
        flag=0;
        memset(map,0,sizeof(map));
        s=0;t=n+1;
        for (long long i=1;i<=n;i++)
        {
            scanf("%s",ss);
            for (long long j=0;j<n;j++)
            {
                if (ss[j]==‘O‘) map[i][j+1]=1;
                else if (ss[j]==‘N‘) map[i][j+1]=2;
            }
        }
        work(1);
        if (flag==1)
            work(2);
        if (flag==1) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
时间: 2024-10-12 23:30:53

BZOJ 3504 危桥的相关文章

bzoj千题计划137:bzoj [CQOI2014]危桥

http://www.lydsy.com/JudgeOnline/problem.php?id=3504 往返n遍,即单向2*n遍 危桥流量为2,普通桥流量为inf 原图跑一遍最大流 交换b1,b2再跑一遍最大流 如果两次的结果都等于(an+bn)*2 则可以 证明参见http://www.cnblogs.com/chenyushuo/p/5139556.html #include<queue> #include<cstdio> #include<cstring> #i

【BZOJ】【3504】【CQOI2014】危桥

网络流/最大流 比较裸的最大流= = 无向图上走来回其实就等价与走两遍>_> 如果路径有相交其实不影响答案的 比较恶心的是两个人路过同一座桥,但走的方向不同互相抵消流量了…… 其实只要在第一遍跑网络流以后如果为Yes,就将其中一人的起点终点交换,再跑一遍就可以了 1 /************************************************************** 2 Problem: 3504 3 User: Tunix 4 Language: C++ 5 Res

【BZOJ 3504】[Cqoi2014]危桥

Description Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1.某些岛屿之间有桥相连,桥上的道路是双 向的,但一次只能供一人通行.其中一些桥由于年久失修成为危桥,最多只能通行两次.Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2 到al算一次往返).同时,Bob希望在岛屿bl和b2之间往返bn次.这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行.请问Alice和 Bob能完成他们的愿望吗? Input 本题有多组测试数据. 每组数据第一

BZOJ 3504 【Cqoi2014】危桥 最大流

题意:链接 方法:最大流 解析:这道题其实第一眼看上去是(和谐)题,然后发现水水的写完后WA了,然后从网上下来数据来观测数据,发现自己WA的地方都是同一个地方,之后上网上看了看其他人的姿势,算是懂了这道题吧. 首先读完题后,第一眼被这个往返卡了一会,后来发现,假如说从A到B,AB间是危桥的话,那你顶多在其中往返一次,也就是对应流量为1,如此的话,因为无相,所以B到A也必然有流量为1的一条路,在加上点细节修饰以及自己手花个图就能明白. 接下来我就以为这道题已经完事了,直接写了发最大流一跑发现WA了

3504: [Cqoi2014]危桥

3504: [Cqoi2014]危桥 链接 分析: 首先往返的可以转化为全是“往”,那么只要将容量除以2即可. 然后S向a1连边容量为an(除以2之前为2*an),S向a2连边容量为an,b1,b2向T连边容量为bn.原图上的边,建双向边保存. 这样会存在从a1流向b2的流量,当然也有b1流向a2的流量,考虑如何判断这种情况. 将b1,b2交换,然后重新跑一遍,判断是否满流即可. 第一遍最大流的时候,假设a1->b2流了x的流量,那么有 a1->a2:an-x, a1->b2:x, b1

bzoj3504【CQOI2014】危桥

3504: [Cqoi2014]危桥 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1161  Solved: 587 [Submit][Status][Discuss] Description Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1.某些岛屿之间有桥相连,桥上的道路是双 向的,但一次只能供一人通行.其中一些桥由于年久失修成为危桥,最多只能通行两次.Alice希望在岛屿al和a2之间往返an次(从al到a2再从

[CQOI2014][bzoj3504] 危桥 [最大流]

题面 传送门 思路 这道题中惟一的特别之处,就在于"危桥"这一个只能走两次的东西 我的第一想法是做一个dp,但是这道题只需要能不能走,也没有必要 网络流?貌似是个很好的选择 我们把所有边作为无向边加入图中,流量上限inf 危桥则作为上限2的无向边 从源点连边到a1b1,汇点连边到a2b2,流量都是2*an或2*bn,相当于一次把两遍走了 最后,只要看看最大流不是(2*an+2*bn) 然而有个问题,万一我们最终求得的最大流中,是a1流到b2.b1流到a2呢? 此时有一个好办法:我们把源

Luogu3163 [CQOI2014]危桥 ---- 网络流 及 一个细节的解释

Luogu3163 [CQOI2014]危桥 题意 有$n$个点和$m$条边,有些边可以无限次数的走,有些边这辈子只能走两次,给定两个起点和终点$a_1 --> a_2$(起点 --> 终点)和$b_1 --> b_2$(起点 --> 终点),询问是否可以让$a_1 --> a_2$往返$a_n$次,让$b_1 --> b_2$往返$b_n$次 题解 思路 思路还是比较好想的,就是原图连双向边,然后炒鸡源汇连$a_n*2$和$b_n*2$判断满流是否为$(a_n+b_n

P3163 [CQOI2014]危桥

传送门 我是看不出这玩意儿和网络流有什么关系-- 我们把图中的所有边都当成无向边加入图中,容量为\(inf\) 危桥的容量为\(2\) 从源点到\(a1,b1\)连边容量为\(an*2\),\(a2,b2\)到汇点连边容量\(bn*2\),相当于一次把两边都走完 然后跑一遍看看是否满流即可 然而这样会有一个问题,就是最终求得的最大流是\(a1\)流向\(b2\)或\(a2\)流向\(b1\) 于是再从源点向\(a1\)和\(b2\)连边,\(a2\)和\(b1\)向汇点连边,再跑一遍看看是否满流