原本考場切了的,結果代碼沒保存,爆炸成80,自閉了。
考場上我是一個一個部分分作的,因此這裏我也一個一個部分分寫。數組
這個檔位是針對樣例寫的。。。由於不寫我就過不了樣例。。。
顯然若是有一個1操做就輸出YES,沒有就看相不相等完事。。。
貼一個沒有什麼用的代碼。spa
inline void Solve_0pts() { if(flg1==1) { printf("YES\n"); } else if(a[1]==b[1]) { printf("YES\n"); } else { printf("NO\n"); } return ; }
1.若是隻有1操做,那很顯然,只要\(a1-b1=a2-b2\)就完事了。
2.若是隻有2操做,那也很顯然,只要\(a1-b1==b2-a2\)就完事了。
3.若是1,2操做都有,那麼假設\(a1+k1+k2=b1\),\(a2+k1-k2=b2\),合併一下就能夠獲得\(a1+a2-b1-b2=-2*k2\),因此只要做差而後斷定一下是否是偶數就能夠了。
貼一個有點用的代碼。code
inline void Solve_60pts() { if(flg1) { if(a[1]-b[1]==a[2]-b[2]) { printf("YES\n"); return; } } if(flg2) { if(a[1]-b[1]==b[2]-a[2]) { printf("YES\n"); return; } } if(flg1&&flg2) { if((a[1]+a[2]-b[1]-b[2])%2==0) { printf("YES\n"); return; } } printf("NO\n"); }
發現被連接的兩個點的值能夠互相流動,因而把連接的點在a和b數列裏分別縮點,這裏用並查集實現。因爲同一個集合裏的點的值能夠互相流動,因此這裏只要a數列和b數列每一個對應集合裏的點權和相同,那麼就必定是合法的,不然不合法,代碼也比較好寫。string
inline int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } inline void merge(int x,int y) { int fx=find(x); int fy=find(y); va[fy]+=va[fx]; va[fx]=0;fa[fx]=fy; } inline void Solve_80pts() { for(R int i=1;i<=n*2;i++) fa[i]=i; for(R int i=1;i<=n;i++) va[i]=a[i]; for(R int i=1;i<=n;i++) va[n+i]=b[i]; for(R int i=1;i<=m;i++) { int x=u[i],y=v[i]; if(find(x)==find(y)) continue; merge(x,y); merge(x+n,y+n); } for(R int i=1;i<=n;i++) if(find(i)==i) { if(va[i]!=va[i+n]) { printf("NO\n"); return; } } printf("YES\n"); }
爲了方便,先用一個sm數組存下a與b對應位置的差值。
發現80分縮點的作法十分溫馨,因此先把操做2縮點,而後就只剩下操做1了。因爲操做2已經縮點,操做1再縮點感受不太現實,因而考慮連邊(好玄學)。 把1操做的兩個點連邊以後(注意是連縮點以後的)。而後繼續開始手玩樣例,發現假若有兩個點\((x,y)\),使得這兩個點之間有一條長度爲偶數的路徑,那這兩個點之間也是能夠相互交流權值的。更特別一點的是,若是一個聯通塊裏面有一個長度爲奇數的環,那任意兩個點之間都會有一條長度爲偶數的路徑。爲何呢,由於環上的點顯然是有的,環外的點若是到一個點不通過環長度爲奇數,那就去跑一邊環就變成偶數了,因此這個命題成立。而後就能夠把有奇環的聯通塊當作一個點了。那麼這樣的一個塊,
若是差值的和或者差是偶數,就是能夠的,不然就不行。注意若是一個點連成了自環,那麼也是能夠的算成這一種塊。若是這個塊剛好是一個二分圖,那麼黑白染色以後,權值就只能夠在黑點集合中的點之間和白點集合中的點之間各自流動,由於同一個集合中的任意兩個點的距離一定是偶數。因此就計算黑點差值之和與白點的差值之和是否相同就能夠了。個人代碼中沒有統計和,是直接一邊染色一邊相減的。對於單獨的點,咱們也把它當作一個二分圖來處理便可。部分代碼就懶得丟了,就是完整代碼裏100pts的部分(忽然反應過來,那我上面丟代碼幹啥???)it
#include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define R register #define ll long long const int MAXN=2e5+10; int n,m; int a[MAXN],b[MAXN]; int opt[MAXN],u[MAXN],v[MAXN]; int flg1=0,flg2=0; inline void Init() { scanf("%d%d",&n,&m); for(R int i=1;i<=n;i++) scanf("%d",&a[i]); for(R int i=1;i<=n;i++) scanf("%d",&b[i]); flg1=flg2=0; for(R int i=1;i<=m;i++) { scanf("%d%d%d",&opt[i],&u[i],&v[i]); if(opt[i]==1) flg1=1; if(opt[i]==2) flg2=1; } } inline void Solve_0pts() { if(flg1==1) { printf("YES\n"); } else if(a[1]==b[1]) { printf("YES\n"); } else { printf("NO\n"); } return ; } inline void Solve_60pts() { if(flg1) { if(a[1]-b[1]==a[2]-b[2]) { printf("YES\n"); return; } } if(flg2) { if(a[1]-b[1]==b[2]-a[2]) { printf("YES\n"); return; } } if(flg1&&flg2) { if((a[1]+a[2]-b[1]-b[2])%2==0) { printf("YES\n"); return; } } printf("NO\n"); } int fa[MAXN]; ll va[MAXN]; inline int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } inline void merge(int x,int y) { int fx=find(x); int fy=find(y); va[fy]+=va[fx]; va[fx]=0;fa[fx]=fy; } inline void Solve_80pts() { for(R int i=1;i<=n*2;i++) fa[i]=i; for(R int i=1;i<=n;i++) va[i]=a[i]; for(R int i=1;i<=n;i++) va[n+i]=b[i]; for(R int i=1;i<=m;i++) { int x=u[i],y=v[i]; if(find(x)==find(y)) continue; merge(x,y); merge(x+n,y+n); } for(R int i=1;i<=n;i++) if(find(i)==i) { if(va[i]!=va[i+n]) { printf("NO\n"); return; } } printf("YES\n"); } int To[MAXN+MAXN],Next[MAXN+MAXN],Head[MAXN],cnt; inline void add(int x,int y) { cnt++; To[cnt]=y; Next[cnt]=Head[x]; Head[x]=cnt; } int sm[MAXN]; int co[MAXN]; int sum,tag; inline void dfs(int x,int col) { co[x]=col; if(col) sum+=sm[x]; else sum-=sm[x]; for(R int i=Head[x];i;i=Next[i]) { int y=To[i]; if(co[y]==-1) dfs(y,col^1); else if(co[x]==co[y]) tag=1; } } inline void Solve_100pts() { memset(Head,0,sizeof(Head)); memset(co,-1,sizeof(co)); cnt=0; for(R int i=1;i<=n;i++) sm[i]=a[i]-b[i]; for(R int i=1;i<=n;i++) fa[i]=i; for(R int i=1;i<=m;i++) { if(opt[i]==1) continue; int x=u[i],y=v[i]; if(find(x)==find(y)) continue; int fx=find(x),fy=find(y); fa[fx]=fy;sm[fy]+=sm[fx];sm[fx]=0; } for(R int i=1;i<=m;i++) { if(opt[i]==2) continue; int x=u[i],y=v[i]; x=find(x);y=find(y); add(x,y);add(y,x); } bool flg=1; for(R int i=1;i<=n;i++) if(find(i)==i&&co[i]==-1) { sum=tag=0; dfs(i,0); for(R int j=Head[i];j;j=Next[j]) if(To[j]==i) tag=1; if(tag==1) { if(sum%2!=0) flg=0; } else { if(sum!=0) flg=0; } } if(flg) printf("YES\n"); else printf("NO\n"); } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int test;scanf("%d",&test); while(test--) { Init(); if(n==1) {Solve_0pts(); continue;} if(n<=2) {Solve_60pts();continue;} if(flg1==0&&flg2==1) {Solve_80pts();continue;} Solve_100pts(); } return 0; }
然而這並不能改變我總分100的事實,自閉了。。。io