zoukankan      html  css  js  c++  java
  • bzoj3590: [Snoi2013]Quare

    bzoj3590: [Snoi2013]Quare

    根据题意,图中显然不能有桥,所以可以先用tarjan找桥判“imposibal”。

    数据这么小,状压吧,我们可以把这个过程看成这样:我们已经有了一个强连通分量,那么我们要把一个点加入进这个强连通分量,可以找到一条包含这个点的链,且让链的两端都在这个强连通分量里。这么想好像挺可行,那么我们开始设计状态。 首先,f[x]表示x中的点组成强联通分量的最小花费。 g[x][y][S]表示一条链,两端点为x,y,整条链经过S里的点的最小花费。 H[0/1][x][S]表示x点向S中的点的连边的最小值和次小值。 然后就可以愉快的做出来了。

    h可以暴力枚举解决:

     1        for(int S=0;S<(1<<n);S++)
     2             for(int i=1;i<=n;i++)
     3             if((S|(1<<(i-1)))!=S)        
     4             {
     5                 for(int j=f(i);j;j=n(j))
     6                 if((S|(1<<(v(j)-1)))==S)
     7                     if(w(j)<h[0][i][S])
     8                     {
     9                         h[1][i][S]=h[0][i][S];
    10                         h[0][i][S]=w(j);
    11                     }
    12                     else if(w(j)<h[1][i][S])h[1][i][S]=w(j);
    13             }
    14             else h[0][i][S]=h[1][i][S]=0;

    g也是一个状压dp,对于x,y,将y分离出来,枚举出边:

     1         memset(g,0x7f,sizeof(g));
     2         for(int S=0;S<(1<<n);S++)
     3         for(int i=1;i<=n;i++)
     4             for(int j=1;j<=n;j++)    
     5                 if( (( S|(1<<(i-1)) )==S) && (( S|(1<<(j-1)) )==S) )
     6                     if(i==j && ( S&~(1<<(i-1)) )==0)g[i][j][S]=0;
     7                     else if(i!=j)    
     8                         for(int k=f(j);k;k=n(k))        
     9                         if( ((1<<(v(k)-1))|S)==S )
    10                         g[i][j][S]=min(g[i][j][S],g[i][v(k)][S&~(1<<(j-1))]+w(k));                

    这里要注意循环顺序,我开始把S放下边就死了。

    然后就是求f了:

     1      memset(f,0x7f,sizeof(f));
     2         for(int i=0;i<n;i++)f[1<<(i)]=0;
     3         for(int S=0;S<(1<<n);S++)
     4         for(int s=0;s<(1<<n);s++)
     5         if((s|S)==S)
     6             for(int x=1;x<=n;x++)
     7             if(((1<<(x-1))|s)!=s && ((1<<(x-1))|S)==S)
     8             for(int y=1;y<=n;y++)
     9             if(((1<<(y-1))|s)!=s && ((1<<(y-1))|S)==S)
    10             {
    11                 if(x!=y)f[S]=min(f[S],1ll*f[s]+g[x][y][S&~s]+h[0][x][s]+h[0][y][s]);
    12                 else    f[S]=min(f[S],1ll*f[s]+g[x][y][S&~s]+h[0][x][s]+h[1][y][s]);
    13             }
    #include<iostream>
    #include<cstring>
    #include<bitset>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #define MAXN 15
    #define MP(a,b) make_pair(a,b)
    #define min(a,b) ((a)<(b)?(a):(b))
    #define ma(x) memset(x,0,sizeof(x))
    using namespace std;
    struct edge
    {
    	int u,v,w,nxt;
    	#define u(x)  ed[x].u
    	#define v(x)  ed[x].v
    	#define w(x)  ed[x].w
    	#define n(x)  ed[x].nxt
    }ed[100];
    int first[MAXN],num_e=1;
    #define f(x) first[x]
    int T,n,m;
    
    int f[1<<13];
    int g[13][13][1<<13];
    int h[2][13][1<<13];
    
    int dfn[MAXN],low[MAXN],cnt;
    bool bridge[100],pd;
    void tarjan(int x,int edg)
    {
    	dfn[x]=low[x]=++cnt;
    	for(int i=f(x);i;i=n(i))
    	if(!dfn[v(i)])
    	{
    		tarjan(v(i),i),low[x]=min(low[x],low[v(i)]);
    		if(low[v(i)]>dfn[x])bridge[i]=bridge[i^1]=1;
    	}
    	else if(i!=(edg^1))low[x]=min(low[x],dfn[v(i)]);
    }
    void init()
    {
    	ma(ed);ma(first);ma(f);ma(g);ma(h);ma(dfn);ma(low);ma(bridge);
    	pd=cnt=0;num_e=1;
    }
    inline void add(int u,int v,int w);
    signed main()
    {
    //	freopen("in.txt","r",stdin);
    
    	scanf("%d",&T);
    	while(T--)
    	{
    		init();
    		scanf("%d%d",&n,&m);
    		int a,b,c;
    		for(int i=1;i<=m;i++)
    		{
    			scanf("%d%d%d",&a,&b,&c);
    			add(a,b,c);add(b,a,c);
    		}
    		for(int i=1;i<=n;i++)
    		if(!dfn[i])tarjan(i,0);	
    		for(int i=2;i<=num_e;i++)
    		if(bridge[i]){puts("impossible");pd=1;break;}
    		if(pd)continue;
    		memset(h,0x7f,sizeof(h));
    		for(int S=0;S<(1<<n);S++)
    			for(int i=1;i<=n;i++)
    			if((S|(1<<(i-1)))!=S)		
    			{
    				for(int j=f(i);j;j=n(j))
    				if((S|(1<<(v(j)-1)))==S)
    					if(w(j)<h[0][i][S])
    					{
    						h[1][i][S]=h[0][i][S];
    						h[0][i][S]=w(j);
    					}
    					else if(w(j)<h[1][i][S])h[1][i][S]=w(j);
    			}
    			else h[0][i][S]=h[1][i][S]=0;
    		memset(g,0x7f,sizeof(g));
    		for(int S=0;S<(1<<n);S++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)	
    				if( (( S|(1<<(i-1)) )==S) && (( S|(1<<(j-1)) )==S) )
    					if(i==j && ( S&~(1<<(i-1)) )==0)g[i][j][S]=0;
    					else if(i!=j)	
    						for(int k=f(j);k;k=n(k))		
    						if( ((1<<(v(k)-1))|S)==S )
    						g[i][j][S]=min(g[i][j][S],g[i][v(k)][S&~(1<<(j-1))]+w(k));
    		memset(f,0x7f,sizeof(f));
    		for(int i=0;i<n;i++)f[1<<(i)]=0;
    		for(int S=0;S<(1<<n);S++)
    		for(int s=0;s<(1<<n);s++)
    		if((s|S)==S)
    			for(int x=1;x<=n;x++)
    			if(((1<<(x-1))|s)!=s && ((1<<(x-1))|S)==S)
    			for(int y=1;y<=n;y++)
    			if(((1<<(y-1))|s)!=s && ((1<<(y-1))|S)==S)
    			{
    				if(x!=y)f[S]=min(f[S],1ll*f[s]+g[x][y][S&~s]+h[0][x][s]+h[0][y][s]);
    				else    f[S]=min(f[S],1ll*f[s]+g[x][y][S&~s]+h[0][x][s]+h[1][y][s]);
    			}
    		printf("%d
    ",f[(1<<n)-1]);
    	}
    }
    inline void add(int u,int v,int w)
    {
    	++num_e;
    	u(num_e)=u;
    	v(num_e)=v;
    	w(num_e)=w;
    	n(num_e)=f(u);
    	f(u)=num_e;
    }
    
  • 相关阅读:
    ORA12518 TNS:监听程序无法分发客户机连接的解决办法
    纯css手风琴效果
    css2实现尖角箭头式导航
    html+css基础
    iOS开发之压缩与解压文件
    一种简便的ios图片加密方法对图片进行base64编码
    将自己的应用程序显示在报刊杂志中
    [转]苹果iOS 5限制应用本地存储问题
    [转]苹果开发者帐号(Company)申请流程
    [转]IOS6.0框架及功能更新小结
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11186749.html
Copyright © 2011-2022 走看看