首先 这是一个并查集= =
这道题其实明白了还挺简单的qwq
思路:
因为只看仇恨值最大的一对儿,所以把他们从大到小排序,越大的就尽量分开,直到不能再分为止qwq
- q[x]表示x最大的敌人(x对q[x]的仇恨值最大);
- 如果x已经有了最大的敌人q[x],那么y就该跟q[x]分到一起;否则q[x] = y;
- 所以并查集存的不是两个*!存的是“因为有共同敌人而被(勉为其难的)划分到一起的罪犯”;
- 这几个并查集由于“敌人的敌人”一点点合并到一起;
- 当目前最大的一对儿敌人已经被分到一个*的时候,就说明分不开了,输出。
一些细节:
- 初始化(fa[i] = i)
- 判断父亲的时候要用getfather(x)而不是fa[x](因为还没求...)(所以还是先写个xx = getfather(x)吧!)
- 同样的,合并的时候,用“xx = getfather(x); yy = getfather(y); fa[x] = y;”,
- 不能写fa[fa[x]] (fa又不是函数!),也不能写getfather(getfather(x)) (getfather也不是整数!)
- 结构体p存的是罪犯关系对数,每一个代表a,b的编号和他们的仇恨值c,所以数组大小是1e6(RE了4次qaq) ——“那你为啥开2e5”
- 如果有冲突的话输出并直接return 0,没有的话循环结束后就输出0!(这个不看题解自己是想不到的qwq)
#include<cstdio> #include<algorithm> using namespace std; const int maxn = 20005; int fa[maxn],q[maxn]; int n,m; struct abc { int a,b,c; } p[200005]; int cmp(abc x,abc y) { return x.c > y.c; } int getfather(int x) { if(x == fa[x])return x; fa[x] = getfather(fa[x]); return fa[x]; } void add(int x,int y){ x = getfather(x); y = getfather(y); fa[x] = y; } int main() { scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) fa[i] = i; for(int i = 1; i <= m; i++) scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c); sort(p+1,p+m+1,cmp); for(int i = 1; i <= m; i++) { if(getfather(p[i].a) == getfather(p[i].b)){ printf("%d",p[i].c); return 0; } if(!q[p[i].a])q[p[i].a] = p[i].b; else add(q[p[i].a],p[i].b); if(!q[p[i].b])q[p[i].b] = p[i].a; else add(q[p[i].b],p[i].a); } printf("0"); return 0; }