Placing Lampposts
2016-01-29 20:07
190 查看
题意:
在一个无向无环图上放置灯盏,保证灯的数量最少的同时被两盏灯照亮的边数尽量大.
思路:
把被两盏灯照亮的边数尽量大转化成被一盏灯照到的边尽量少,如果有两个需要优化的量v1,v2,要求首先满足v1最少,在v1最少的前提下v2最少,则设一个M,M > max(v2)-min(v2).
然后设一个x,使x=Mv1+v2.
在一个无向无环图上放置灯盏,保证灯的数量最少的同时被两盏灯照亮的边数尽量大.
思路:
把被两盏灯照亮的边数尽量大转化成被一盏灯照到的边尽量少,如果有两个需要优化的量v1,v2,要求首先满足v1最少,在v1最少的前提下v2最少,则设一个M,M > max(v2)-min(v2).
然后设一个x,使x=Mv1+v2.
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int M = 2000; const int maxn = 1010; vector<int> adj[maxn]; bool vis[maxn]; int f[maxn][2]; int n, m; void dfs(int u) { vis[u] = true; f[u][0] = 0; f[u][1] = M;//M*v1,放一个灯,加一次M for(int i=0; i<adj[u].size(); i++) { int v = adj[u][i]; if(vis[v])continue; dfs(v); f[u][0] += f[v][1]+1;//父结点不放灯,v2+1 if(f[v][0]<f[v][1]) f[u][1] += f[v][0]+1;//如果子节点不放灯,v2+1 else f[u][1] += f[v][1]; } } int main() { int kase; scanf("%d", &kase); while(kase--) { scanf("%d%d", &n, &m); for(int i=0; i<n; i++) adj[i].clear(); int u, v; for(int i=0; i<m; i++) { scanf("%d%d", &u, &v); adj[u].push_back(v); adj[v].push_back(u); } memset(f, 0, sizeof(f)); memset(vis, false, sizeof(vis)); int ans = 0; for(int i=0; i<n; i++) { if(vis[i] == false) { dfs(i); ans += min(f[i][0], f[i][1]);//两种决策取其小. } } printf("%d %d %d\n", ans/M, m-ans%M, ans%M); } return 0; }
相关文章推荐
- C++ lambda笔记
- 体绘制之光线投射算法(附源码)
- [R语言]读取文件夹下所有子文件夹中的excel文件,并根据分类合并。
- 四、Lua协同程序
- Fragment填充ToolBar菜单
- HDU2457 DNA repair(AC自动机+DP)
- Linux Bash的基本功能 输出重定向
- oracle数据导出导入
- scikit-learn入门到精通(三):监督学习
- asm基础——汇编中的结构体
- mysql如何让一个存储过程定时执行
- jdk目录详解及其使用方法
- 51nod 1358:浮波那契 构造矩阵
- Oracle 游标使用全解
- RabbitMQ消息分发模式----"Publish/Subscribe"发布/订阅模式
- 编程算法 - 扑克牌的顺子 代码(C)
- javascript设计模式实践之职责链--具有百叶窗切换图片效果的JQuery插件(三)
- PullToRefreshListView 使用介绍
- antuomake 生成configure的使用
- Hunan University 2009 the 5th Programming Contest - 11443- 8 numbers problem