zoukankan      html  css  js  c++  java
  • hdu 4640 Island and study-sister

    bfs+状态压缩求出所有的状态,然后由于第一个节点需要特殊处理,可以右移一位剔除掉,也可以特判。然后采用集合的操作,

    #pragma comment(linker,"/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <queue>
    using namespace std;
    #define inf 0x3f3f3f3f
    
    int n, m, cnt;
    int head[17], next[17 * 17 * 2 + 3][3], dp[1 << 17][17], dis[1 << 17], num[1 << 17];
    
    void add (int u, int v, int w)
    {
    	next[cnt][1] = v;
    	next[cnt][2] = w;
    	next[cnt][0] = head[u];
    	head[u] = cnt++;
    }
    
    void bfs ()
    {
    	queue<pair<int, int> > q;
    	q.push(make_pair(0, 1));
    	dp[1][0] = 0;
    	while (!q.empty()){
    		pair<int, int> p = q.front();
    		q.pop();
    		int su = p.second;
    		int u = p.first;
    		for (int i = head[u]; i != -1; i = next[i][0]){
    			int v = next[i][1];
    			int w = next[i][2];
    			int sv = su|(1 << v);
    			if(dp[sv][v] > dp[su][u] + w){
    				dp[sv][v] = dp[su][u] + w;
    				q.push(make_pair(v, sv));
    			}
    		}
    	}
    }
    
    int main ()
    {
    	//freopen ("in.txt", "r", stdin);
    	int t, count = 0;
    	scanf ("%d", &t);
    	while (t--)
    	{
    		scanf ("%d %d", &n, &m);
    		int u, v, w;
    		for (int i = 0; i < n; ++i) head[i] = -1;
    		for (int i = (1 << n) - 1; i >= 0; --i){
    			dis[i] = inf;
    			num[i] = inf;
    			for (int j = 0; j < n; ++j) dp[i][j] = inf;
    		}
    		cnt = 0;
    		for (int i = 0; i < m; ++i){
    			scanf ("%d %d %d", &u, &v, &w);
    			add (u - 1, v - 1, w);
    			add (v - 1, u - 1, w);
    		}
    		scanf ("%d", &m);
    		v = 0;
    		for (int i = 0; i < m; ++i){
    			scanf ("%d", &u);
    			v |= (1 << (u - 1));
    		}
    		v >>= 1;
    		if (!m || (m == 1 && u == 1)){
    			printf("Case %d: 0
    ", ++count);
    			continue;
    		}
    		bfs ();
    		u = inf;
    		w = (1 << (n-1)) - 1;
    		for(int i = 1; i < (1 << n); ++i)
    			for(int j = 0; j < n; ++j) 
    				dis[i >> 1] = min(dis[i >> 1], dp[i][j]);		
    		for (int i = 1; i <= w; ++i)
    			for (int j = i; j; j = (j - 1) & i)
    				num[i] = min(num[i], max(dis[j], dis[i ^ j]));
    		for (int i = 1; i <= w; ++i)
    			for(int j = i; j; j = (j - 1) & i)
    			if((i & v) == v) u = min(u, max(num[j], dis[i ^ j]));
    		if (u == inf) u = -1;
    		printf("Case %d: %d
    ", ++count, u);
    	}
    	return 0;
    }


  • 相关阅读:
    luoguP4389 付公主的背包 多项式exp
    bzoj3456 城市规划 多项式求In
    luoguP4491 [HAOI2018]染色 广义容斥原理 + FFT
    计蒜之道2019复赛题解
    Educational Codeforces Round 66 (Rated for Div. 2)
    [CodeChef-ANUDTQ] Dynamic Trees and Queries
    M-SOLUTIONS Programming Contest
    Codeforces Global Round 3
    PKUSC2019题解
    [LOJ#3120][Luogu5401][CTS2019]珍珠(容斥+生成函数)
  • 原文地址:https://www.cnblogs.com/pangblog/p/3341753.html
Copyright © 2011-2022 走看看