IcePrincess_1968's World

I'll always miss you like a darling.

TopCoder SRM468C: MallSecurity 题解

这道题模型还是挺显然的
这看起来是一个N分图,但当N是偶数的时候,这就是一个二分图,奇数层的在左边,偶数层的在右边,原题就是要求一个二分图的最大独立集,∣=N
(我脑残了忘了这个结论还用最小割推了一波:要求最多能选中多少个点,相当于求最少扔掉多少个点,对于每条边,左边的点连向源点,流量为1,表示如果割掉这条边,相当于这个点不选,损失1;右边的点连向汇点,流量为1,表示如果割掉这条边,相当于这个点不选,损失1;两个点之间连一条INF的边,我们考虑到如果这个网络还存在一条从s到t的增广路,那一定有一条本质上是snode1node2t的路径,snode1node2t都没有割开,相当于这两个点同时选了,它们又相邻,这是不合法的,所以中间的INF的意义实际上是你不能通过割掉这条边来改变原图中的相邻关系
然后发现这个图的最小割就是二分图最大匹配…猛然想起结论QAQ)
然后我们发现如果N是奇数这个图就不是二分图
但我们注意到10N50node∣≤100,所以点数最少的那层点数一定小于10,所以我们只要2n枚举一下这一层的每个点选不选,并处理一下这层对相邻两层的影响,那么剩下的就又是一个二分图了
于是这道题就做完了
代码很难写

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <utility>
#include <cctype>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#define LL long long
#define LB long double
#define x first
#define y second
#define Pair pair<int,int>
#define pb push_back
#define pf push_front
#define mp make_pair
#define LOWBIT(x) x & (-x)
using namespace std;

const int MOD=1e9+7;
const LL LINF=2e16;
const int INF=1e9;
const int magic=348;
const double eps=1e-10;
const double pi=3.14159265;

inline int getint()
{
    char ch;int res;bool f;
    while (!isdigit(ch=getchar()) && ch!='-') {}
    if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
    while (isdigit(ch=getchar())) res=res*10+ch-'0';
    return f?res:-res;
}

class MallSecurity
{
    int n,num[148],t,sum[148];
    struct Edge {int ind1,ind2,layer;}edge[10048],tmp[10048],ttmp[10048];int etot,ttot,tttot;
    bool bef[148],aft[148];
    int head[100048],to[200048],nxt[200048],f[200048],tot;
    inline void addedge(int s,int t,int cap)
    {
        to[++tot]=t;nxt[tot]=head[s];head[s]=tot;f[tot]=cap;
        to[++tot]=s;nxt[tot]=head[t];head[t]=tot;f[tot]=0;
    }
    inline void clear()
    {
        etot=0;tot=1;t=0;
        memset(head,0,sizeof(head));
        memset(num,0,sizeof(num));memset(sum,0,sizeof(sum));
        ttot=tttot=0;
    }
    inline int STRING_TO_INT(string s)
    {
        int res=0,i;
        for (i=0;i<int(s.size());i++) res=res*10+s[i]-'0';
        return res;
    }
    inline void doit_single(string s)
    {
        int x,y,z,p1,p2;
        p1=s.find(' ');p2=s.find(' ',p1+1);
        x=STRING_TO_INT(s.substr(0,p1));
        y=STRING_TO_INT(s.substr(p1+1,p2-p1-1));
        z=STRING_TO_INT(s.substr(p2+1,int(s.size())-p2));
        edge[++etot]=Edge{x,y,z};
    }
    inline void doit_edge(vector<string> info)
    {
        string s="";int i;
        for (i=0;i<int(info.size());i++) s+=info[i];s+=",";
        int pos,pos1;
        for (pos=0;pos<=int(s.size())-1;pos=pos1+1)
        {
            pos1=s.find(',',pos);
            doit_single(s.substr(pos,pos1-pos));
        }
    }
    inline void Count()
    {
        int i;
        for (i=1;i<=etot;i++)
        {
            num[edge[i].layer]=max(num[edge[i].layer],edge[i].ind1);
            num[edge[i].layer%n+1]=max(num[edge[i].layer%n+1],edge[i].ind2);
        }
        for (i=1;i<=n;i++) t+=num[i],sum[i]=sum[i-1]+num[i];
        t++;
    }
    inline int getind(int layer,int ind)
    {
        return sum[layer-1]+ind;
    }
    inline void construct_edge()
    {
        int i,j,node1,node2;
        for (i=1;i<=etot;i++)
        {
            node1=getind(edge[i].layer,edge[i].ind1);node2=getind(edge[i].layer%n+1,edge[i].ind2);
            if (edge[i].layer%2==0) swap(node1,node2);
            addedge(node1,node2,INF);
        }
        for (i=1;i<=n;i++)
            for (j=1;j<=num[i];j++)
            {
                node1=getind(i,j);
                if (i%2==1) addedge(0,node1,1); else addedge(node1,t,1);
            }
    }
    int depth[100048];queue<int> q;
    inline bool bfs()
    {
        int i,x,y;
        for (i=0;i<=t;i++) depth[i]=-1;
        depth[0]=0;q.push(0);
        while (!q.empty())
        {
            x=q.front();q.pop();
            for (i=head[x];i;i=nxt[i])
            {
                y=to[i];
                if (depth[y]==-1 && f[i])
                {
                    depth[y]=depth[x]+1;
                    q.push(y);
                }
            }
        }
        if (depth[t]==-1) return false; else return true;
    }
    inline int dfs(int x,int maxf)
    {
        if (x==t || !maxf) return maxf;
        int i,y,now,minf,ans=0;
        for (i=head[x];i;i=nxt[i])
        {
            y=to[i];
            if (depth[y]==depth[x]+1 && f[i])
            {
                minf=min(maxf-ans,f[i]);
                now=dfs(y,minf);
                f[i]-=now;f[i^1]+=now;ans+=now;
            }
            if (ans>=maxf) return ans;
        }
        if (!ans) depth[x]=0;
        return ans;
    }
    inline bool judge(int cur,int gap)
    {
        if (cur<gap) return cur%2==1; else return cur%2==0;
    }
    public:
        inline int maxGuards(int N,vector<string> escDescription)
        {
            n=N;clear();
            doit_edge(escDescription);
            Count();
            if (N%2==0)
            {
                construct_edge();
                int ans=0;
                while (bfs()) ans+=dfs(0,2e9);
                return sum[n]-ans;
            }
            else
            {
                int minn=INF,minpos,Mask,i,j;
                for (i=1;i<=n;i++)
                    if (num[i]<minn) minn=num[i],minpos=i;
                for (i=1;i<=etot;i++)
                    if (edge[i].layer==minpos || edge[i].layer==(minpos-1==0?n:minpos-1))
                        tmp[++ttot]=edge[i];
                    else
                        ttmp[++tttot]=edge[i];
                etot=tttot;
                for (i=1;i<=etot;i++) edge[i]=ttmp[i];
                int res=0,curans;
                for (Mask=0;Mask<=(1<<minn)-1;Mask++)
                {
                    tot=1;for (i=0;i<=t;i++) head[i]=0;
                    memset(bef,true,sizeof(bef));memset(aft,true,sizeof(aft));
                    curans=__builtin_popcount(Mask);
                    for (i=1;i<=ttot;i++)
                        if (tmp[i].layer==minpos)
                        {
                            if (Mask&(1<<(tmp[i].ind1-1))) aft[tmp[i].ind2]=false;
                        }
                        else
                        {
                            if (Mask&(1<<(tmp[i].ind2-1))) bef[tmp[i].ind1]=false;
                        }
                    for (i=1;i<=etot;i++)
                    {
                        int node1=getind(edge[i].layer,edge[i].ind1),node2=getind(edge[i].layer%n+1,edge[i].ind2);
                        if (!judge(edge[i].layer,minpos)) swap(node1,node2);
                        addedge(node1,node2,INF);
                    }
                    for (i=1;i<=n;i++)
                    {
                        if (i==minpos) continue;
                        for (j=1;j<=num[i];j++)
                        {
                            if (i==minpos%n+1 && !aft[j]) continue;
                            if (i==(minpos-1==0?n:minpos-1) && !bef[j]) continue;
                            int nde=getind(i,j);curans++;
                            if (judge(i,minpos)) addedge(0,nde,1); else addedge(nde,t,1);
                        }
                    }
                    while (bfs()) curans-=dfs(0,2e9);
                    res=max(res,curans);
                }
                return res;
            }
        }
};

/*---Debug Part---*/
/*
int main ()
{
    MallSecurity A;int nn;vector<string> ss;
    while (scanf("%d",&nn)!=EOF)
    {
        int mm;mm=getint();string s;ss.clear();
        while (mm--)
        {
            getline(cin,s);
            ss.pb(s);
        }
        printf("%d\n",A.maxGuards(nn,ss));
    }
    return 0;
}
*/
/*
10
2
1 1 1,1 1 2,1 1 3,1 1 4,1 1 5,1 1 6,1 1 7,1 1 8,1 
1 9,1 1 10
10 9
1 1 7,1 2 9,2 1
 8,1 2 6,1 1 8,1 2 3,1 2 2,2 
2 4,1 1 1,2 1 2,3 2 3,1 1 5,2 1 1,4 
1 7,1 1 10,3 2 5,1 2 5,3 3 1,
3 2 8,3 1 2,1 1 3,4 4 2,2
 4 6,4 2 5,2 3 3,6 4 1,5 2 8,1 3 6,1 3 7,
4 3 8,1 3 8,5 2 3,4 2 8,2 6 7,1 3 9,
1 1 4,6 1 1,2 3 1,5 1 5,6 1 8,5 
2 2,3 2 10,3 3 9,1 5 2,4 1 1,1 5 10
*/
阅读更多
想对作者说点什么? 我来说一句

Topcoder介绍及Arena使用方法

2008年05月25日 657KB 下载

没有更多推荐了,返回首页

不良信息举报

TopCoder SRM468C: MallSecurity 题解

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭