A - Wrestling Match (二分图染色)
题意略坑(没有说好的玩家一定能打过差的玩家啊啊~~)
典型的二分图染色问题,每个玩家看成一个点,把相互较量过的玩家之间连边,好的玩家染成黑色,差的玩家染成白色。先把能确定颜色的点都确定下来,然后剩下的点判断是不是二分图,推导过程中发现矛盾立即返回No。如果一个点没有和其他任何点相连且颜色不确定也返回No。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1000+10; 5 int hd[N],ne,n,m,X,Y,col[N]; 6 struct E {int v,nxt;} e[20010]; 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 8 bool dfs(int u,int c) { 9 if(~col[u])return col[u]==c; 10 col[u]=c; 11 for(int i=hd[u]; ~i; i=e[i].nxt) { 12 int v=e[i].v; 13 if(!dfs(v,col[u]^1))return 0; 14 } 15 return 1; 16 } 17 bool solve() { 18 for(int u=1; u<=n; ++u)if(~col[u]) { 19 for(int i=hd[u]; ~i; i=e[i].nxt) { 20 int v=e[i].v; 21 if(!dfs(v,col[u]^1))return 0; 22 } 23 } 24 for(int u=1; u<=n; ++u)if(!~col[u]) { 25 if(!~hd[u])return 0; 26 if(!dfs(u,0))return 0; 27 } 28 return 1; 29 } 30 31 int main() { 32 while(scanf("%d%d%d%d",&n,&m,&X,&Y)==4) { 33 memset(hd,-1,sizeof hd),ne=0; 34 memset(col,-1,sizeof col); 35 while(m--) { 36 int u,v; 37 scanf("%d%d",&u,&v); 38 addedge(u,v); 39 addedge(v,u); 40 } 41 while(X--) {int x; scanf("%d",&x); col[x]=1;} 42 while(Y--) {int x; scanf("%d",&x); col[x]=0;} 43 puts(solve()?"YES":"NO"); 44 } 45 return 0; 46 }
B - Regular Number (字符串匹配Shift-And算法+bitset优化)
Shift-And算法,有点抽象,其大致思想是利用前缀移位的方法,对每个数字建立一个bitset,把模板串中所有能出现的位置标上1,然后把原串从头到尾扫一遍,每扫到一个位置,把这个位置加到另一个bitset里,然后和这个位置上的数对应的bitset相与,清除不合法的位置。如果一个位置能够“安全”到达第n-1位,则说明匹配成功,ans++。
时间卡得很死,要用gets和puts才能过。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=5e6+10; 5 int n; 6 char s[N]; 7 bitset<1000+10> a[10],b; 8 9 int main() { 10 while(scanf("%d",&n)==1) { 11 for(int i=0; i<10; ++i)a[i].reset(); 12 b.reset(); 13 for(int i=0; i<n; ++i) { 14 int x,y; 15 scanf("%d",&x); 16 while(x--) { 17 scanf("%d",&y); 18 a[y].set(i); 19 } 20 } 21 getchar(),gets(s); 22 for(int i=0; s[i]; ++i) { 23 b=(b<<1).set(0)&a[s[i]^48]; 24 if(b.test(n-1)) { 25 char ch=s[i+1]; 26 s[i+1]='