1 条题解
-
0
自动搬运
来自洛谷,原作者为

隔壁泞2的如心
AFO|以某种事物作为代价,以某种代价作为契机……?搬运于
2025-08-24 22:40:32,当前版本为作者最后更新于2022-11-09 00:28:25,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
令人发指的究极辛巴达多合一题。
给出题人点个赞,数据一点都不水,造出了好多非平凡四元环(
要想做这题,首先你看到这平面图就知道得转对偶,具体在推荐题目第一个矿区的题解里就有。
然后你看到这么一堆位运算就知道要拆位,从高位到低位贪心。
显然,要想拦截成功,从最高位开始:
-
如果外星人在这位有能量,那么我们必须要让外星人花费这点能量,不然之后全堵死也没法拦截。
-
如果外星人在这位没有能量,那么我们可以在这里就把外星人堵死,或者先放它一马,然后外星人不再能通过任何含有此位的边,看看之后会不会有更优的解。
我们的任务变成了如何求出在某位拦截外星人的代价。显然我们加边权时不会进位,这等价于让一些边获得此位,使得所有含有此位(或者之前放过外星人的位)的边构成割。转成对偶图之后,原图的割等价于新图的环。但是以优于 的复杂度求无向图的最小环,这我不会啊!
再次观察题面,题目隐含了一个极强的条件:图没有重边!没有重边的平面图边数有上限,为 ,因此原图中不会没有点的度数不大于 ,由于所有边代价一样,我们只要把那个原图中度数最小的点所连的所有边删去,就可以获得每位不大于 的代价!
因此,我们可以依次判断新图的最小环是否是 ,如果都不是就是 。具体地,我们依次判断以下条件。
-
原图是否联通
-
新图是否有自环
-
新图是否有重边
-
原图是否有度数为3的点,如果没有,新图是否有三元环。(套用三元环计数方法)
-
原图是否有度数为4的点,如果没有,新图是否有四元环。(套用四元环计数方法)
然后这题就做完了,我们发现,这看似友好的题面里面隐藏了好多板子……
下面是一些坑点:
-
自环重边不能一起查。
-
联通自环重边必须要在新图上查,特判原图度数行不通。
-
存新图的数组一定要往大了开,新图的点数可能比原图多很多。
下面是代码,不是很可读,也不能拿来对拍,没啥必要看……
#include<cstdio> #include<vector> #include<map> #include<cstring> #include<cassert> #include<cmath> #include<algorithm> #define int long long using namespace std; struct par{ int a,b; friend bool operator<(par n1,par n2){if(n1.a==n2.a)return n1.b<n2.b;return n1.a<n2.a;} }; map<par,int> ppc; vector<int> l1[165432],l2[165432],sol[135],l3[165432]; int n,m,k,px[165432],py[165432],nxt[305416],t[305416],val[305416],tq[305416],bel[305416],dx[305416],dy[305416],t2[305416],dic[305416],mp[165432],xp[165432],cp[165432],ppv[165432]; bool cmp(int a,int b){ return atan2(dx[a],dy[a])<atan2(dx[b],dy[b]); } bool cmp2(int a,int b){ return t2[a]<t2[b]; } int ppcdfs(int now,int arg){ if(ppv[now])return 0; ppv[now]=1; int crr=0; for(int i=0;i<l1[now].size();i++){ if(!(val[l1[now][i]]&arg))crr+=ppcdfs(t[l1[now][i]],arg); } return crr+1; } void sv(int now,int arg){ memset(nxt,-1,sizeof(nxt));memset(bel,-1,sizeof(bel));memset(dic,0,sizeof(dic));memset(t2,0,sizeof(t2));memset(t2,0,sizeof(t2));memset(ppv,0,sizeof(ppv)); int mid=77777777,mida=0; for(int i=1;i<=n;i++){ int cnt=0,mind=0; for(int j=0;j<l1[i].size();j++){ if(!(val[l1[i][j]]&arg))tq[cnt++]=l1[i][j],mind++; } mid>mind?mid=mind,mida=i:0; sort(tq,tq+cnt,cmp); for(int i=0;i<cnt-1;i++)nxt[tq[i]]=tq[i+1]^1;nxt[tq[cnt-1]]=tq[0]^1; } int cnt=0; for(int i=0;i<m*2;i++){ int nw=i; if(nxt[nw]==-1||bel[nw]!=-1)continue; cnt++; while(!~bel[nw]){ bel[nw]=cnt; nw=nxt[nw]; dic[cnt]++; } } for(int i=1;i<=cnt;i++)l2[i].clear(),l3[i].clear(); ppc.clear(); if(ppcdfs(1,arg)!=n)return; if(!mid)return; if(mid==1){ for(int j=0;j<l1[mida].size();j++)if(!(val[l1[mida][j]]&arg))sol[now].push_back(l1[mida][j]); return; } for(int i=0;i<m*2;i++){ if(bel[i]==-1)continue; l2[bel[i]].push_back(i); t2[i]=bel[i^1]; if(bel[i]==bel[i^1]){ sol[now].push_back(i); return; } if(dic[bel[i^1]]>dic[bel[i]]||(dic[bel[i^1]]==dic[bel[i]]&&bel[i^1]>bel[i]))l3[bel[i]].push_back(i); } if(mid<=2){ for(int j=0;j<l1[mida].size();j++)if(!(val[l1[mida][j]]&arg))sol[now].push_back(l1[mida][j]); return; } for(int i=0;i<m*2;i++){ if(bel[i]==-1)continue; if(ppc.find({bel[i],bel[i^1]})!=ppc.end()){ sol[now].push_back(i); sol[now].push_back(ppc[{bel[i],bel[i^1]}]); return; } ppc[{bel[i],bel[i^1]}]=i; } for(int i=1;i<=cnt;i++){ sort(l2[i].begin(),l2[i].end(),cmp2); for(int j=0;j<l2[i].size()-1;j++){ assert(t2[l2[i][j]]!=i); if(t2[l2[i][j]]==t2[l2[i][j+1]]){ sol[now].push_back(l2[i][j]); sol[now].push_back(l2[i][j+1]); return; } } } if(mid<=3){ for(int j=0;j<l1[mida].size();j++)if(!(val[l1[mida][j]]&arg))sol[now].push_back(l1[mida][j]); return; } memset(mp,-1,sizeof(mp));memset(xp,0,sizeof(xp)); for(int i=1;i<=cnt;i++){ for(int j=0;j<l3[i].size();j++){ int ts=t2[l3[i][j]];xp[ts]=i;mp[ts]=l3[i][j]; } for(int j=0;j<l3[i].size();j++){ int ts=t2[l3[i][j]]; if(ts==i)continue; for(int h=0;h<l3[ts].size();h++){ if(xp[t2[l3[ts][h]]]==i){ sol[now].push_back(l3[ts][h]); sol[now].push_back(mp[t2[l3[ts][h]]]); sol[now].push_back(l3[i][j]); return; } } } } if(mid<=4){ for(int j=0;j<l1[mida].size();j++)if(!(val[l1[mida][j]]&arg))sol[now].push_back(l1[mida][j]); return; } memset(cp,-1,sizeof(cp));memset(mp,-1,sizeof(mp));memset(xp,0,sizeof(xp)); for(int i=1;i<=cnt;i++){ for(int j=0;j<l2[i].size();j++){ int ts=t2[l2[i][j]]; for(int h=0;h<l3[ts].size();h++){ if(t2[l3[ts][h]]==i)continue; if(xp[t2[l3[ts][h]]]==i){ sol[now].push_back(cp[t2[l3[ts][h]]]); sol[now].push_back(mp[t2[l3[ts][h]]]); sol[now].push_back(l3[ts][h]); sol[now].push_back(l2[i][j]); return; } xp[t2[l3[ts][h]]]=i; mp[t2[l3[ts][h]]]=l3[ts][h]; cp[t2[l3[ts][h]]]=l2[i][j]; } } } if(mid<=5){ for(int j=0;j<l1[mida].size();j++)if(!(val[l1[mida][j]]&arg))sol[now].push_back(l1[mida][j]); return; } assert(0); } signed main(){ scanf("%*lld%lld%lld%lld",&n,&m,&k); for(int i=1;i<=n;i++)scanf("%lld%lld",px+i,py+i); for(int i=0;i<m;i++){ int in1,in2,in3; scanf("%lld%lld%lld",&in1,&in2,&in3); assert(in1!=in2); l1[in1].push_back(i*2);l1[in2].push_back(i*2+1); t[i*2]=in2;t[i*2+1]=in1;val[i*2]=val[i*2+1]=in3; assert(t[i*2]!=t[i*2+1]); dx[i*2]=px[in2]-px[in1];dy[i*2]=py[in2]-py[in1]; dx[i*2+1]=-px[in2]+px[in1];dy[i*2+1]=-py[in2]+py[in1]; } int cur1=0,cur2=0,anss=44444444,fin=66554432; for(int i=30;i>=0;i--){ sv(i,(1<<i)|cur1); if(k&(1<<i))cur2+=sol[i].size(); else{ (anss>cur2+sol[i].size())?(anss=(cur2+sol[i].size()),fin=i):0; cur1|=(1<<i); } } ppc.clear(); for(int i=30;i>=fin;i--){ if(i!=fin&&((k&(1<<i))==0))continue; for(int j=0;j<sol[i].size();j++){ par p1={t[sol[i][j]],t[sol[i][j]^1]};if(p1.a>p1.b)swap(p1.a,p1.b); if(ppc.find(p1)==ppc.end())ppc[p1]=(1<<i); else ppc[p1]=ppc[p1]|(1<<i); } } printf("%u\n",ppc.size()); for(auto i=ppc.begin();i!=ppc.end();i++){ printf("%lld %lld %lld\n",(i->first).a,(i->first).b,i->second); } } -
- 1
信息
- ID
- 8115
- 时间
- 5000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者