UVALive - 5906 Smoking gun(差分约束系统+拓扑排序)
2015-08-21 00:04
246 查看
题目大意:给出N个人的坐标和M个听到枪声的顺序,问是否有一个开枪顺序能满足着M个条件,是一个还是多少?
解题思路:典型的差分约束系统,设第i个人开枪时间为ti
假设a先听到b的枪声,再听到c的枪声
那么就要满足一个条件
tb + dis(a,b) <= tc + dis(a,c)(这里本来都要除以音速的,但此处可以省略)
由这个不等式构造边,具体构造就不说了,了解差分约束系统的都会构造,如果不会,证明你还不太了解
接着判断,如果有环,表明条件不可能全部成立
在条件成立的情况下,拓扑一下,如果拓扑失败,表明有多个开枪顺序了,如果成功,就只有一个了
解题思路:典型的差分约束系统,设第i个人开枪时间为ti
假设a先听到b的枪声,再听到c的枪声
那么就要满足一个条件
tb + dis(a,b) <= tc + dis(a,c)(这里本来都要除以音速的,但此处可以省略)
由这个不等式构造边,具体构造就不说了,了解差分约束系统的都会构造,如果不会,证明你还不太了解
接着判断,如果有环,表明条件不可能全部成立
在条件成立的情况下,拓扑一下,如果拓扑失败,表明有多个开枪顺序了,如果成功,就只有一个了
[code]#include <cstdio> #include <cstring> #include <iostream> #include <map> #include <vector> #include <cmath> #include <queue> #include <set> using namespace std; #define N 110 #define M 1010 struct Node{ string s; int x, y; }node ; struct Edge{ int u, v, next; double c; }E[M]; map<string,int> name; vector<int> vec ; set<int> Tuopu; int n, m, tot; int head ; char str1 , str2 , str3 ; void AddEdge(int u, int v, double c) { E[tot].u = u; E[tot].v = v; E[tot].c = c; E[tot].next = head[u]; head[u] = tot++; } double distance(int i, int j) { int x = node[i].x - node[j].x; int y = node[i].y - node[j].y; return sqrt(1.0 * x * x + 1.0 * y * y); } void init() { scanf("%d%d", &n, &m); name.clear(); Tuopu.clear(); string s1, s2, s3; int x, y; for (int i = 1; i <= n; i++) { cin >> node[i].s >> node[i].x >> node[i].y; name[node[i].s] = i; vec[i].clear(); } memset(head, -1, sizeof(head)); tot = 0; // u + dist1 <= v + dist2 for (int i = 0; i < m; i++) { scanf("%s heard %s firing before %s", str1, str2, str3); s1 = str1; s2 = str2; s3 = str3; double dist1 = distance(name[s2], name[s1]); double dist2 = distance(name[s3], name[s1]); int u = name[s2]; int v = name[s3]; Tuopu.insert(u); Tuopu.insert(v); AddEdge(v, u, dist2 - dist1); } } #define INF 0x3f3f3f3f #define esp 1e-8 double d ; bool vis ; int in , cnt ; bool spfa(int s) { memset(cnt, 0, sizeof(cnt)); memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++) d[i] = INF; queue<int> Q; d[s] = 0; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = head[u]; ~i; i = E[i].next) { int v = E[i].v; if (d[v] > d[u] + esp + E[i].c) { d[v] = d[u] + E[i].c; if (!vis[v]) { vis[v] = true; Q.push(v); if (++cnt[v] >= n) return false; } } } vis[u] = false; } for (int i = 1; i <= n; i++) if (d[i] < -esp) { vec[i].push_back(s); in[s]++; Tuopu.erase(s); } return true; } void solve() { memset(in, 0, sizeof(in)); for (int i = 1; i <= n; i++) if (!spfa(i)) { printf("IMPOSSIBLE\n"); return ; } queue<int> ans; while (Tuopu.size()) { if (Tuopu.size() > 1) { printf("UNKNOWN\n"); return ; } int t = *Tuopu.begin(); ans.push(t); Tuopu.erase(t); for (int i = 0; i < vec[t].size(); i++) { --in[vec[t][i]]; if (in[vec[t][i]] == 0) Tuopu.insert(vec[t][i]); } } cout << node[ans.front()].s; ans.pop(); while (!ans.empty()) { cout << " " << node[ans.front()].s; ans.pop(); } printf("\n"); } int main() { int test; scanf("%d", &test); while (test--) { init(); solve(); } return 0; }
相关文章推荐
- Handler发送Message
- 题目:Maximal Square
- GNOME Linux 桌面入门
- 如何使用 Cachet 部署自承载系统状态页面
- LLVM 五月上海迷你工作坊,欢迎你的到来
- 剖析Python的Tornado框架中session支持的实现代码
- Python编程中的异常处理教程
- Python中条件判断语句的简单使用方法
- Python中for循环和while循环的基本使用方法
- win7系统配置php+Apache+mysql环境的方法
- PHP的Yii框架使用中的一些错误解决方法与建议
- MYSQL5.X重置root密码 (windows系统)
- SpringMVC简单构造restful, 并返回json——(一)
- resin
- vim常用命令
- PHP的Yii框架的基本使用示例
- 使用PHP进行微信公众平台开发的示例
- 详细解读PHP的Yii框架中登陆功能的实现
- jQuery实现大转盘抽奖活动仿QQ音乐代码分享
- 纯javascript实现图片延时加载方法