icpc:problems:luogup3068
problems | |
---|---|
名称 | Party Invitations S |
题目编号 | P3068 |
题目链接 | luogu.com.cn/… |
来源 | Luogu |
算法分类 | 拓扑排序 |
难易程度 | 容易 |
Party Invitations S
想法
记录每个点拥有的朋友圈,记录每个朋友圈拥有的点。对朋友圈进行类似于拓扑排序的操作,当朋友圈中的还剩最后一个时,将所有与这个最后一个牛的朋友圈均加入队列,重新更新这些朋友圈。直到没有朋友圈能更新为止。
代码实现
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int M = 250010; const int N = 1e6+10; struct node { int v, next; }; node toCir[M]; node toPoint[M]; int headToCir[N], headToPoint[N], cntToCir, cntToPoint, size[M]; bool vis[M], ans[N]; void add_edge_Cir(int cow, int cir) { toCir[++cntToCir].v = cir; toCir[cntToCir].next = headToCir[cow]; headToCir[cow] = cntToCir; return ; } void add_edge_Poi(int cow, int cir) { toPoint[++cntToPoint].v = cow; toPoint[cntToPoint].next = headToPoint[cir]; headToPoint[cir] = cntToPoint; return ; } int main() { memset(headToCir, -1, sizeof(headToCir)); memset(headToPoint, -1, sizeof(headToPoint)); int n, g, cow; scanf("%d %d", &n, &g); for(int i=1; i<=g; i++) { scanf("%d", &size[i]); for(int j=1; j<=size[i]; j++) { scanf("%d", &cow); add_edge_Cir(cow, i); add_edge_Poi(cow, i); } } queue<int>qu; ans[1] = true; for(int i=headToCir[1]; ~i; i=toCir[i].next) { int cir = toCir[i].v; vis[cir] = true; qu.push(cir); } while(!qu.empty()) { int now = qu.front(); qu.pop(); vis[now] = false; int cnt = 0, last = 0; for(int i=headToPoint[now]; ~i; i=toPoint[i].next) { int point = toPoint[i].v; if(ans[point]) cnt++; else last = point; } if(cnt == size[now]-1) { ans[last] = true; for(int i=headToCir[last]; ~i; i=toCir[i].next) { int cir = toCir[i].v; if(vis[cir])continue; qu.push(cir); vis[cir] = true; } } } int ansCnt = 0; for(int i=1; i<=n; i++) if(ans[i]) ansCnt++; printf("%d", ansCnt); return 0; }
/app/www/public/data/pages/icpc/problems/luogup3068.txt · 最后更改: 2024/02/18 14:50 由 温婕莺