求边数最小且为奇数条边的环
枚举每一条边进行dfs。
剪枝:
1.搜索时记录每个点的搜索深度,如果现在的深度小于所记录的深度,才能访问这个点。
2.当出现最小的3时,就不用继续搜索了。
#include <iostream> #include <vector> using namespace std; struct Node { int a, b; }ns[20005]; int n, m, tm[1002], cnt, ans, ca=1, idx; int mp[1002][1002], from, to; vector<int> vec[1002]; void input() { int i, j, a, b; scanf( "%d %d", &n, &m ); for( i=0; i<=n; ++i ) vec[i].clear(); for( i=0; i<=n; ++i ) { tm[i] = 0; for( j=0; j<=n; ++j ) { mp[i][j] = 0; } } idx = 0; for( i=0; i<m; ++i ) { scanf( "%d %d", &a, &b ); if( mp[a][b] ) continue; ns[idx].a = a; ns[idx].b = b; idx ++; vec[a].push_back(b); vec[b].push_back(a); mp[a][b] = mp[b][a] = 1; } } void dfs( int u, int deep ) { int i, j, sz; if( mp[u][to] ) { ++ deep; if( (deep&1) && deep < ans ) { ans = deep; } return; } if( ans == 3 || deep >= ans) return; if( deep >= tm[u] && tm[u] ) return; tm[u] = deep; sz = vec[u].size(); for( i=0; i<sz; ++i ) dfs( vec[u][i], deep+1 ); } void solve() { int i, j, a, b; ans = 1000000; for( i=0; i<idx; ++i ) { from = ns[i].a; to = ns[i].b; mp[from][to] = mp[to][from] = 0; memset( tm, 0, sizeof(tm) ); dfs( from, 1 ); if( ans == 3 ) break; mp[from][to] = mp[to][from] = 1; } if( ans == 1000000 ) printf( "Case %d: Poor JYY.\n", ca++ ); else printf( "Case %d: JYY has to use %d balls.\n", ca++, ans ); } int main() { // freopen( "c:/aaa.txt", "r", stdin ); int T; scanf( "%d", &T ); while( T-- ) { input(); solve(); } return 0; }
差不多的一题:
2.hdoj 1599 find the mincost route
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; struct Node { int a, b; }ns[1002]; int mp[102][102], n, m, ans, cnt; vector<int> vec[102]; void input() { int i, j, a, b, c; for( i=0; i<=n; ++i ) vec[i].clear(); for( i=0; i<=n; ++i ) { for( j=0; j<=n; ++j ) { mp[i][j] = 1000000; } } cnt = 0; for( i=0; i<m; ++i ) { scanf( "%d %d %d", &a, &b, &c ); if( c > mp[a][b] ) continue; if( mp[a][b] == 1000000 ) { ns[cnt].a = a; ns[cnt++].b = b; vec[a].push_back(b); vec[b].push_back(a); } mp[a][b] = mp[b][a] = c; } /* for( i=1; i<=n; ++i ) { for( j=1; j<=n; ++j ) { printf( "%10d ", mp[i][j]); } printf( "\n" ); }*/ } int spfa( int from, int to ) { int Min[102], i, j, u, v, sz; bool mark[102]; queue<int> Q; for( i=0; i<=n; ++i ) { Min[i] = 1000000; mark[i] = 0; } Min[from] = 0; Q.push( from ); mark[from] = 1; while( !Q.empty() ) { u = Q.front(); Q.pop(); mark[u] = 0; sz = vec[u].size(); for( i=0; i<sz; ++i ) { v = vec[u][i]; if( mp[u][v] == 1000000 ) continue; if( Min[v] > Min[u] + mp[u][v] ) { Min[v] = Min[u] + mp[u][v]; if( !mark[v] ) { Q.push(v); mark[v] = 1; } } } } return Min[to]; } void solve() { int i, j, from, to, tp, temp; ans = 1000000; for( i=0; i<cnt; ++i ) { from = ns[i].a; to = ns[i].b; tp = mp[from][to]; mp[from][to] = mp[to][from] = 1000000; temp = spfa( from, to ); if( temp + tp < ans ) ans = temp + tp; mp[from][to] = mp[to][from] = tp; } if( ans == 1000000 ) puts( "It's impossible." ); else printf( "%d\n", ans ); } int main() { // freopen( "c:/aaa.txt", "r", stdin ); while( scanf("%d %d", &n, &m) != EOF ) { input(); solve(); } return 0; }