zoukankan      html  css  js  c++  java
  • 【BZOJ】2140 稳定婚姻

    【解析】Hash,离散化。Tarjan

    [分析]
    对于每一个名字。首先离散化成编号。
    用hash或者其它,反正不要最主要的即可了。否则O(N^2L)会爆掉。
    然后请參考:http://www.cnblogs.com/Randolph87/p/3757817.html

    [吐槽]
    难得吐槽一下,做这道题居然做了一个上午,開始暴力求标号,然后一直TLE。
    中间map的数据范围少开了N,也试过几次WA。
    这不是水题吗。为什么会是一个艰难的Accept...

    [小结]
    求二分图完备匹配的必要边,①存不存在增广环?

    O(N^2) ②直接试着删去依照hungery找完备匹配 O(N^3)。



    [代码]

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    
    typedef unsigned long long ULL;
    const int N=8002;
    const int M=20001;
    const int L=12;
    const int T=37;
    const int LMT=100009;
    
    int n,m;
    struct G
    {
    	int v,nxt;
    }map[M+N];
    int tt,hd[N];
    int dfn[N],pre[N],ct;
    int edge[N][2];
    int v[N],color[N],stk[N],cc;
    char t[L];
    struct T
    {
    	char s[L];
    	int nxt;
    }hash[N];
    int num,hh[LMT];
    
    inline void ins(int u,int v)
    {
    	map[++tt].v=v;
    	map[tt].nxt=hd[u];
    	hd[u]=tt;
    }
    
    void tarjan(int now)
    {
    	dfn[now]=pre[now]=++ct;
    	stk[++stk[0]]=now,v[now]=1;
    	for (int k=hd[now];k;k=map[k].nxt)
    	{
    		if (v[map[k].v]==2) continue;
    		if (v[map[k].v]==1) 
    		{
    			if (pre[map[k].v]<dfn[now]) dfn[now]=pre[map[k].v];
    			continue;
    		}
    		tarjan(map[k].v);
    		if (dfn[map[k].v]<dfn[now]) dfn[now]=dfn[map[k].v];
    	}
    	if (pre[now]==dfn[now])
    	{
    		cc++;
    		for (;stk[stk[0]]!=now;stk[0]--)
    			color[stk[stk[0]]]=cc,v[stk[stk[0]]]=2;
    		color[stk[stk[0]]]=cc; v[stk[stk[0]--]]=2;
    	}
    }
    
    inline ULL h(void)
    {
    	ULL sum=0; int lt=strlen(t);
    	for (int i=0;i<lt;i++) sum=sum*T+t[i]-'0';
    	return sum;
    }
    
    int pos(void)
    {
    	int key=h()%LMT;
    	for (int k=hh[key];k;k=hash[k].nxt)
    		if (!strcmp(hash[k].s,t)) return k;
    	memmove(hash[++num].s,t,sizeof t);
    	hash[num].nxt=hh[key];
    	return hh[key]=num;
    }
    
    int main(void)
    {	
    	int t1,t2;
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%s",t); t1=pos();
    		scanf("%s",t); t2=pos();
    		edge[i][0]=t1,edge[i][1]=t2;
    		ins(t1,t2);
    	}
    	scanf("%d",&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%s",t); t1=pos();
    		scanf("%s",t); t2=pos();
    		ins(t2,t1);
    	}
    	
    	for (int i=1;i<=n;i++)
    		if (!v[edge[i][0]]) tarjan(edge[i][0]);
    	
    	for (int i=1;i<=n;i++)
    		printf("%s
    ",color[edge[i][0]]==color[edge[i][1]]?"Unsafe":"Safe");
    	
    	return 0;
    }
  • 相关阅读:
    一些小题
    文件操作_菜单<代码>
    文件操作
    linux基础学习
    列表,元组,字典
    系统集成项目管理工程师高频考点(第六章)
    系统集成项目管理工程师高频考点(第五章)
    系统集成项目管理工程师高频考点(第四章)
    系统集成项目管理工程师高频考点(第三章)
    信息系统项目管理师高频考点(第一章)
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6891092.html
Copyright © 2011-2022 走看看