HDU 5811 (拓扑排序 LIS)
来源:互联网 发布:transmac制作mac安装盘 编辑:程序博客网 时间:2024/06/05 07:47
题目链接:点击这里
题意:给定n个人之间的强壮关系(没有传递性),分成两个组,首先判断每一组是否能够通过某种排列使得前面的人都比后面的人强壮。如果可以,最多能从2组中选几个人到1组使得1组通过排列仍然使得前面的人都比后面的人强壮。
因为是个竞赛图,只要没有环就行(DAG),所以直接拓扑如果出队列数刚好等于节点数就可以,在拓扑的时候顺便记下拓扑序给先前的两组按照拓扑序排完。至于最多能够扔过去的点,本来想的是贪心,一个点能够扔到1组当且仅当能打败他的点的最大拓扑序小于他能打败的最小拓扑序。但是有可能把一个点扔过去后导致更多的点扔不过去。所以考虑第二组每个点能够放在第一组的位置,然后第二组所有的点就都有一个位置了,然后求一次LIS就是最多的点数。
O(
#include <cstring>#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cmath>#include <queue>#include <set>using namespace std;#define maxn 1005#define maxm 2000005int n, m;int g[maxn][maxn];struct E { int v, next;}edge[maxm];int head[maxn], cnt;bool vis[maxn];int a[maxn], b[maxn];int ida[maxn], idb[maxn];int degree[maxn];//入度struct node { int x, y; bool operator < (const node &a) const { return x < a.x || (x == a.x && y < a.y); }};set <node> gg;void add_edge (int u, int v) { edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;}int q[maxn];bool topo (int *a, int n, int *id) { int root = 0; for (int i = 1; i <= n; i++) { if (!degree[a[i]]) { root = a[i]; break; } } int num = 0; if (!root) return 0; num++; int tou = 0, wei = 0; q[wei++] = root; id[root] = 1; int index = 1; while (tou < wei) { int u = q[tou++]; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; degree[v]--; if (!degree[v]) { q[wei++] = v; num++; id[v] = ++index; } } } if (num < n) return 0; return 1;}bool cmp1 (const int &x, const int &y) { return ida[x] < ida[y];}bool cmp2 (const int &x, const int &y) { return idb[x] < idb[y];}int h[maxn], dp[maxn];#define INF 10000000int LIS (int *a, int n) { if (!n) return 0; int ans = 0; for (int i = 1; i <= n; i++) h[i] = INF; for (int i = 1; i <= n; i++) { int k = lower_bound (h+1, h+1+n, a[i])-h; ans = max (ans, k); h[k] = a[i]; } return ans;}int x[maxn];void solve () { //T2 memset (head, -1, (n+10) * sizeof (int)); memset (degree, 0, (n+10) * sizeof (int)); cnt = 0; for (int i = 1; i <= n-m; i++) { for (int j = i+1; j <= n-m; j++) { if (g[b[i]][b[j]]) add_edge (b[i], b[j]), degree[b[j]]++; else add_edge (b[j], b[i]), degree[b[i]]++; } } if (!topo (b, n-m, idb)) { printf ("NO\n"); return ; } //T1 for (int i = 1; i <= m; i++) { for (int j = i+1; j <= m; j++) { if (g[a[i]][a[j]]) add_edge (a[i], a[j]), degree[a[j]]++; else add_edge (a[j], a[i]), degree[a[i]]++; } } if (!topo (a, m, ida)) { printf ("NO\n"); return ; } printf ("YES "); gg.clear (); sort (a, a+m, cmp1); sort (b, b+n-m, cmp2); for (int i = 1; i <= n-m; i++) { int pos1 = 0, pos2 = 0; int Min = 1000000, Max = 0;//连向它的最大的 它连向的最小的 for (int u = 1; u <= m; u++) { if (g[a[u]][b[i]]) { if (ida[a[u]] > Max) { Max = ida[a[u]]; pos1 = a[u]; } } else { if (ida[a[u]] < Min) { Min = ida[a[u]]; pos2 = a[u]; } } } if (Min > Max) { gg.insert ((node) {Max, idb[b[i]]}); } } //LIS int len = 0; for (set<node>::iterator it = gg.begin (); it != gg.end (); it++) { x[++len] = it->y; } printf ("%d\n", LIS (x, len));}int scan () { char ch = ' '; while (ch < '0'|| ch > '9') ch = getchar (); int x = 0; while (ch <= '9' && ch >= '0') x = x*10+ch-'0', ch = getchar (); return x;}int main () { while (scanf ("%d%d", &n, &m) == 2 && n+m) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { g[i][j] = scan (); } vis[i] = 0; } for (int i = 1; i <= m; i++) { a[i] = scan (); vis[a[i]] = 1; } int cnt = 0; for (int i = 1; i <= n; i++) if (!vis[i]) { b[++cnt] = i; } solve (); } return 0;}/*10 50 1 1 1 1 1 1 1 1 10 0 1 1 1 1 1 1 1 10 0 0 1 1 1 1 1 1 10 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 10 0 0 0 0 0 1 1 1 10 0 0 0 0 0 0 1 1 10 0 0 0 0 0 0 0 1 10 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 3 5 7 910 30 1 1 1 1 1 1 1 1 10 0 1 1 1 1 1 1 1 10 0 0 1 1 1 1 1 1 10 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 10 0 0 0 0 0 1 1 1 10 0 0 0 0 0 0 1 1 10 0 0 0 0 0 0 0 1 10 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 10 9 8*/
0 0
- HDU 5811 (拓扑排序 LIS)
- HDU 5811 Colosseo (拓扑排序+LIS)
- HDU 1272 拓扑排序
- HDU 3342 拓扑排序
- [HDU-1285] 拓扑排序
- hdu 1285拓扑排序
- hdu 1285 拓扑排序
- hdu 3342 拓扑排序
- HDU 3342 拓扑排序
- HDU 1285 拓扑排序
- HDU-2647拓扑排序
- hdu 3342 拓扑排序
- hdu 2647 拓扑排序
- hdu 1285 拓扑排序
- hdu Reward(拓扑排序)
- HDU 1285 拓扑排序
- hdu 1285 拓扑排序
- hdu 1285(拓扑排序)
- LeetCode | Search a 2D Matrix
- iOS UI: UIMenuController | InputView 折腾记
- MySQL DBA 面试题目 答疑记 《01》
- Java中接口与实例化【引用】
- 【杭电oj2012】素数判定
- HDU 5811 (拓扑排序 LIS)
- “懒惰”Linux 管理员的 10 个关键技巧
- 【杭电oj2013】蟠桃记
- Lua入门教程
- 网格计算
- 博弈论专题——推理与动态规划相关博弈之POJ2068 POJ3688动态规划)
- 使用IDE开发Spark应用程序
- Lightoj1267 Points in Rectangle (II)(排序+树状数组)
- 【杭电oj20114】青年歌手大奖赛_评委会打分