HDOJ 5278 YJC plays automaton
2015-07-13 12:26
281 查看
记录二元组<i, j>,对原图处理反向建边,然后从终结状态反向bfs搜索就行了。。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 905 #define maxm 10000005 #define eps 1e-7 #define mod 998244353 #define INF 0x3f3f3f3f #define PI (acos(-1.0)) #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R #define pii pair<int, int> #pragma comment(linker, "/STACK:16777216") typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} // head struct Edge { int v1, v2; Edge *next; }*H[maxn][maxn], E[maxm], *edges; int g[maxn][10]; int vis[maxn][maxn]; queue<pii> q; int f[maxn]; int cnt[maxn]; int n, m; void addedges(int u1, int u2, int v1, int v2) { edges->v1 = v1; edges->v2 = v2; edges->next = H[u1][u2]; H[u1][u2] = edges++; } void init() { edges = E; memset(H, 0, sizeof H); } void bfs() { for(int i = 1; i <= n; i++) q.push(mp(0, i)); while(!q.empty()) { int t1 = q.front().first, t2 = q.front().second; q.pop(); if(vis[t1][t2]) continue; vis[t1][t2] = true; for(Edge *e = H[t1][t2]; e; e = e->next) { int v1 = e->v1, v2 = e->v2; q.push(mp(v1, v2)); } } } int find(int u) { return f[u] = f[u] == u ? f[u] : find(f[u]); } void merge(int a, int b) { int aa = find(a), bb = find(b); if(aa == bb) return; f[aa] = bb; cnt[bb] += cnt[aa]; } void work() { int t; memset(vis, 0, sizeof vis); memset(g, 0, sizeof g); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d", &g[i][j]); for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) for(int k = 1; k <= m; k++) { int t1 = g[i][k]; int t2 = g[j][k]; if(t1 > t2) swap(t1, t2); addedges(t1, t2, i, j); } bfs(); for(int i = 1; i <= n; i++) f[i] = i, cnt[i] = 1; for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) if(!vis[i][j]) merge(i, j); for(int i = 1; i <= n; i++) find(i); LL ans = powmod(2, n) - 1; for(int i = 1; i <= n; i++) if(f[i] == i) { ans -= powmod(2, cnt[i]) - 1; ans %= mod; } ans = (ans % mod + mod) % mod; printf("%lld\n", ans); } int main() { while(scanf("%d%d", &n, &m)!=EOF) { init(); work(); } return 0; }
相关文章推荐
- 对于初学者Xcode最常用的快捷键
- 【LeetCode】233. Number of Digit One
- 12.Java5读写锁技术的妙用
- POJ 2828 Buy Tickets(线段树·插队)
- 安卓
- windows 10预览版怎么启用零售模式?
- linux Apache支持asp配置
- java中的注解
- Android 4中点击事件写法
- 一、初级篇——指针(*)、取地址(&)、解引用(*)与引用(&)的区别
- centos安装apache
- 火狐浏览器3.0如何查看网页元素的三维视图
- bzoj3242: [Noi2013]快餐店 树形dp+线段树
- HDU 3584 Cube(三维树状数组)
- 二叉树的建立和遍历
- 分类器总结
- HSL模型与填色的应用
- hdu 1026 bfs+优先级队列
- J2EE的13种核心技术
- uiscrollview 无缝循环滚动