• [POJ1463] Strategic game


    题目链接:##

    传送门

    题目大意:##

    Bob非常享受玩电脑游戏的过程,尤其是策略游戏,但是在有些时候,他因为不能在第一时间找到最佳的策略而十分伤心。 现在,他遇到了一个问题。他必须保卫一个中世纪的城市,有很多道路将整个城市连起来,整体上看上去像一棵树。Bob需要放置尽可能少的士兵,保卫树上所有的边。士兵只能放在节点上,但是却可以保卫所有与这个节点相邻的边。

    题目分析:##

    由于树本身具有二分图的性质,所以这里我把树手动染色转成二分图,然后跑最小点覆盖
    (当然也可以树形dp)

    代码:##

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N (1500 + 5)
    using namespace std;
    inline int read(){
    	int cnt = 0, f = 1; char c;
    	c = getchar();
    	while (!isdigit(c)) {
    		if(c == '-') f = -f;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		cnt = cnt * 10 + c - '0';
    		c = getchar();
    	}
    	return cnt * f;
    }
    int n, nxt[2*N], to[2*N], first[2*N], tot, x, t, y, Float[N], cnt, black, white, ans, match[N];
    bool vis[N];
    struct node{
    	int x;int y;
    }edge[N];
    void add(int x, int y) {
    	 nxt[++tot] = first[x];
    	 first[x] = tot;
    	 to[tot] = y;
    }
    void Dfs(int u){
    	for (register int i = first[u]; i; i = nxt[i]) {
    		int v = to[i];
    		if(!Float[v]) {
    			Float[v] = Float[u] + 1;
    			Dfs(v);
    		}
    	}
    }
    void build_map() {
    	memset (first, 0, sizeof(first));
    	memset (nxt, 0, sizeof(nxt));
    	memset (to, 0, sizeof(to));
    	tot = 0;
    	for (register int i = 1; i <= cnt; i++) {
    		int X = edge[i].x; int Y = edge[i].y;
    		if (Float[X] % 2 == 1) {
    			add(X, Y);
    			if (!vis[X]) {
    				vis[X] = true;
    				black++;
    			}
    			if (!vis[Y]) {
    				vis[Y] = true;
    				white++;
    			}
    		} else {
    			add(Y, X);
    			if (!vis[X]) {
    				vis[X] = true;
    				white++;
    			}
    			if (!vis[Y]) {
    				vis[Y] = true;
    				black++;
    			}
     		}
    	}
    }
    int find(int u) {
    //		cout<<u<<"##"<<endl;
    	for (register int i = first[u]; i; i = nxt[i]) {
    		int v = to[i];
    //		cout<<vis[v]<<" "<<v<<endl;
    		if (vis[v]) {
    		   continue; 
     		} else {
    		   	vis[v] = true;
    		   	if (match[v] == -1||find(match[v])) {
    		   		match[v] = u;
    		   		return 1;
    		   	}
       		}
       	}
       	return 0;
    }
    
    int hungary() {
    	for (register int i = 1; i <= n; i++) match[i] = -1;
    	for (register int i = 1; i <= n; i++) {
    		for (register int j = 1; j <= n; j++) vis[j] = 0;
    		ans += find(i);
    	}
    	return ans;
    }
    
    int main(){
    	while(scanf("%d", &n) != EOF) {
    		memset(first, 0, sizeof(first));
    		memset(nxt, 0, sizeof(nxt));
    		memset(to, 0, sizeof(to));
    		memset(Float, 0, sizeof(Float));
    		memset(vis, 0, sizeof(vis));
    		tot=0; cnt=0; ans=0;
    		for (register int i = 1; i <= n; i++) {
    			x = read();
    			t = read();
    			for (register int j = 1; j <= t; j++) {
    				y = read();
    				edge[++cnt].x = x+1;
    				edge[cnt].y = y+1;
    				add(x+1,y+1);
    				add(y+1,x+1);
    			}
    		}
    		Float[1] = 1;
    		Dfs(1);
    		build_map();
    //		cout<<black<<" "<<white<<endl;
    //		for(register int i = 1; i <= n; i++) cout<<Float[i];
    		int res = hungary();
    		printf("%d
    ", res);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    C#开发规范
    Win32API使用技巧 -- 置顶应用
    Windows开发常用快捷键
    MarkDown简单语法回顾
    样本分布
    复变函数
    set theory
    Oscar的数理统计笔记本
    Oscar的拓扑笔记本
    c语言总结
  • 原文地址:https://www.cnblogs.com/kma093/p/10540883.html
Copyright © 2020-2023  润新知