標籤:style blog http color os 2014
原題: FZU 2169 http://acm.fzu.edu.cn/problem.php?pid=2169
這題貌似有兩種解法,DFS和SPFA,但是DFS怎麼都RE,SPFA也要用鄰接表表示邊,用向量表示的話會TLE,而且用SPFA有一個異或,就是題目說要沿最短路走到都城,但是SPFA是走最短路去消滅叛軍,然後再走回都城,我不知道怎麼回事,不知道能不能有大神解釋。因為這樣的話,有多少叛軍就能消滅多少叛軍了,那就不要用什麼演算法 了,直接一個統計。於是試了一下,居然A了,瞬間變成大水題,我無法再評價這個題目了,就當消遣了。
SPFA法:依次從每個軍隊城市出發做一次SPFA,看到有能到的(肯定能到啊)叛軍就將其消滅。
代碼:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <queue>#define Mod 1000000007using namespace std;#define N 100007struct Edge{ int v,next;}G[2*N];int head[N],tot;int army[N],rebel[N];int vis[N],dis[N];int res;int n,m;void addedge(int u,int v){ G[tot].v = v; G[tot].next = head[u]; head[u] = tot++;}void SPFA(int s){ int i; memset(vis,0,sizeof(vis)); queue<int> que; while(!que.empty()) que.pop(); que.push(s); vis[s] = 1; dis[s] = 0; while(!que.empty()) { int tmp = que.front(); que.pop(); vis[tmp] = 0; for(i=head[tmp];i!=-1;i=G[i].next) { int v = G[i].v; if(dis[v] > dis[tmp] + 1) { dis[v] = dis[tmp]+1; if(!vis[v]) { que.push(v); vis[v] = 1; } } } }}int main(){ int i,j,x; int u,v; while(scanf("%d%d",&n,&m)!=EOF) { memset(army,0,sizeof(army)); memset(rebel,0,sizeof(rebel)); memset(head,-1,sizeof(head)); tot = 0; int cnt = 0; for(i=1;i<=n;i++) { scanf("%d",&rebel[i]); if(rebel[i]) cnt++; } for(i=1;i<=m;i++) scanf("%d",&army[i]); for(i=0;i<n-1;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } res = 0; for(i=1;i<=m;i++) { SPFA(army[i]); for(j=1;j<=n;j++) { if(dis[j] != Mod) { if(rebel[j]) { res += rebel[j]; rebel[j] = 0; cnt--; } } } if(cnt == 0) //已經消滅完 break; } printf("%d\n",res); } return 0;}
View Code
DFS法(Runtime Error):
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#define Mod 1000000007#define ll long longusing namespace std;#define N 100007struct Edge{ int v,next;}G[2*N];int head[N],tot;int army[N],rebel[N];ll sum;int n,m;void addedge(int u,int v){ G[tot].v = v; G[tot].next = head[u]; head[u] = tot++;}int dfs(int u,int val,int fa){ int soni = 0; if(army[u]) //找到軍隊 { sum += val; soni++; } for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(v == fa) continue; soni += dfs(v,val+rebel[u],u); } if(soni > 1) sum -= (soni-1)*rebel[u]; return soni;}int main(){ int i,j,x; int u,v; while(scanf("%d%d",&n,&m)!=EOF) { memset(army,0,sizeof(army)); memset(rebel,0,sizeof(rebel)); memset(head,-1,sizeof(head)); tot = 0; for(i=1;i<=n;i++) scanf("%d",&rebel[i]); for(i=1;i<=m;i++) { scanf("%d",&x); army[x] = 1; } for(i=0;i<n-1;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } sum = 0; dfs(1,0,-1); printf("%lld\n",sum); } return 0;}
View Code
直接統計:
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;#define N 100007int army[N],rebel[N];int res;int n,m;int main(){ int i,j,x; int u,v; while(scanf("%d%d",&n,&m)!=EOF) { memset(rebel,0,sizeof(rebel)); int cnt = 0; res = 0; for(i=1;i<=n;i++) { scanf("%d",&rebel[i]); if(rebel[i]) res += rebel[i]; } for(i=1;i<=m;i++) scanf("%d",&army[i]); for(i=0;i<n-1;i++) scanf("%d%d",&u,&v); if(m == 0) { puts("0"); continue; } printf("%d\n",res); } return 0;}
View Code