|洛谷|搜尋|NOIP2012|P1078 文化之旅
阿新 • • 發佈:2019-01-01
https://www.luogu.org/problem/show?pid=1078
直接搜就好,倒搜可以過最後一個點不超時
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ms(i,j) memset(i,j,sizeof i); int n;//國家總數 int k;//文化總數 int m;//道路總數 int s,t;//始終點 int ci[105];//每個國家的文化 int ki[105][105];//文化排斥情況鄰接矩陣 int edge[105][105];//道路 bool wh[105];//搜尋:是否學了第i種文化 int mini = 100000000;//搜尋:當前最短路 bool vi[105];//搜尋:是否訪問過該節點 int dfs(int u, int cost) { wh[ci[u]] = true;//學習這種文化 vi[u] = true; if (cost>=mini) {vi[u] = false; wh[ci[u]] = false;return 0;}//剪枝 if (u==s)//到達終點 { if (cost<mini) mini = cost; vi[u] = false; wh[ci[u]] = false; return 0; } for (int i=1;i<=n;i++)//列舉所有連邊 { if (edge[u][i]) { if (!vi[i])//沒訪問過那個節點 { bool bj = false; for (int j=1;j<=k;j++)//排斥 { if (ki[ci[i]][j]) if (wh[j]) { bj = true; break; } if (ki[j][ci[i]]) if (wh[ci[i]]) { bj = true; break; } } if (bj) continue;//有排斥,列舉下一個 dfs(i, cost+edge[u][i]);//繼續搜尋 } } } wh[ci[u]] = false; vi[u] = false; } int main() { //freopen("culture.in","r", stdin);freopen("culture.out","w", stdout); scanf("%d%d%d%d%d", &n, &k, &m, &s, &t); for (int i=1;i<=n;i++) scanf("%d", &ci[i]); for (int i=1;i<=k;i++) for (int j=1;j<=k;j++) scanf("%d", &ki[i][j]); ms(edge,127); for (int i=1;i<=m;i++) { int u,v,d; scanf("%d%d%d", &u, &v, &d); if (edge[u][v]>d) edge[u][v] = d; if (edge[v][u]>d) edge[v][u] = d; } ms(vi, false); dfs(t,0); if (mini==100000000) printf("-1\n"); else printf("%d\n", mini); fclose(stdin); fclose(stdout); return 0; }