https://www.nowcoder.com/pat/5/problems
1001 Public Bike Management (30)
看完题目就是最短路、数据范围N<500, C<100
要求多条最短路的情况下, 优先选择运出最少、其次是运入最少
考虑一条最短路径、题目要求路径上每个点都要满足C/2。
使用dij搜索, 用一个pre,vector数组, 存放所有的前置节点、组合可以得到所有最短路径
每条最短路 p a t h i path_i pathi一共有 x i x_i xi个结点计算 v a l u e i = ∣ ∑ j = 1 x i c n t j − x i ∗ C / 2 ∣ value_i=|\sum_{j=1}^{x_i}cnt_j - x_i*C/2| valuei=∣∑j=1xicntj−xi∗C/2∣
然后路径按照value排序、value最小的就是问题的解
#include
#define rep(i,l,r) for(int i=l;i
#define pb push_back
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
struct node{
int v,c;
bool operator < (const node &rhs) const{
return c>rhs.c;
}
};
vector<node> G[N];
VI pre[N];
int dis[N];
bool vis[N];
int value[N];
void dij(int n, int t, int &min_cost)
{
priority_queue<node> que;
rep(i,0,n+1)dis[i] = INF,vis[i] = false;
dis[0] = 0;
que.push((node){0,0});
bool ret = false;
while(!que.empty())
{
node tp = que.top();que.pop();
int u = tp.v;
if (vis[u]) continue;
vis[u] = true;
if (tp.c > min_cost)
return;
if (u == t)
{
min_cost = dis[u];
}
rep(i,0,(int)G[u].size())
{
int v = G[u][i].v, c = G[u][i].c;
if (!vis[v] && dis[v] >= dis[u] + c)
{
if (dis[v] > dis[u] + c)
{
dis[v] = dis[u] + c;
que.push((node){v,dis[v]});
pre[v].clear();
pre[v].push_back(u);
}
else
{
pre[v].push_back(u);
}
}
}
}
}
VVI paths;
int path[N];
void dfs(int u, int fa, int top)
{
path[++top] = u;
if (u == 0)
{
VI tp;
while(top != -1)
tp.push_back(path[top--]);
paths.push_back(tp);
return;
}
rep(i,0,(int)pre[u].size())
{
int v = pre[u][i];
if (v != fa)
{
dfs(v, u, top);
}
}
}
int main()
{
int max_c, n, t, m;
cin>>max_c>>n>>t>>m;
value[0] = 0;
rep(i,1,n+1)
cin>>value[i];
int x,y,z;
rep(i,0,m)
{
cin>>x>>y>>z;
G[x].pb((node){y,z});
G[y].pb((node){x,z});
}
int min_cost = INF;
dij(n,t,min_cost);
VI ans;
dfs(t,-1,-1);
int mmin1 = INF, pos1 = -1, tag = -1;
int mmin2 = INF, pos2 = -1;
rep(i,0,(int)paths.size())
{
int Sum = 0;
rep(j,0,(int)paths[i].size())
Sum += value[paths[i][j]];
int val = ((int)paths[i].size()-1) * max_c / 2 - Sum;
if (val >= 0 && mmin1 > val)
{
mmin1 = val;
pos1 = i;
tag = 1;
}
if (tag == -1 && val < 0 && mmin2 > -val)
{
mmin2 = -val;
pos2 = i;
}
}
int pos=-1, mmin=INF;
if (tag == 1)
{
pos = pos1;
mmin = mmin1;
}
if (tag == -1)
{
pos = pos2;
mmin = mmin2;
}
if (pos != -1)
{
int in = 0, out = 0;
if (tag == 1)
out = mmin;
else
in = mmin;
cout << out << ' ';
int sz = (int)paths[pos].size();
rep(i,0,sz-1)
cout << paths[pos][i] << "->";
cout << paths[pos][sz-1] <<" "<< in << endl;
}
return 0;
}
然后上交代码后发现是错的。 看了数据和讨论区才知道, 自行车中心可以,送出和收回的数量可都不为零。
完全没想到啊。这tm。
然后我修改了一下代码。
#include
#define rep(i,l,r) for(int i=l;i
#define pb push_back
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
struct node{
int v,c;
bool operator < (const node &rhs) const{
return c>rhs.c;
}
};
vector<node> G[N];
VI pre[N];
int dis[N];
bool vis[N];
int value[N];
void dij(int n, int t, int &min_cost)
{
priority_queue<node> que;
rep(i,0,n+1)dis[i] = INF,vis[i] = false;
dis[0] = 0;
que.push((node){0,0});
bool ret = false;
while(!que.empty())
{
node tp = que.top();que.pop();
int u = tp.v;
if (vis[u]) continue;
vis[u] = true;
if (tp.c > min_cost)
return;
if (u == t)
{
min_cost = dis[u];
}
rep(i,0,(int)G[u].size())
{
int v = G[u][i].v, c = G[u][i].c;
if (!vis[v] && dis[v] >= dis[u] + c)
{
if (dis[v] > dis[u] + c)
{
dis[v] = dis[u] + c;
que.push((node){v,dis[v]});
pre[v].clear();
pre[v].push_back(u);
}
else
{
pre[v].push_back(u);
}
}
}
}
}
VVI paths;
int path[N];
void dfs(int u, int fa, int top)
{
path[++top] = u;
if (u == 0)
{
VI tp;
while(top != -1)
tp.push_back(path[top--]);
paths.push_back(tp);
return;
}
rep(i,0,(int)pre[u].size())
{
int v = pre[u][i];
if (v != fa)
{
dfs(v, u, top);
}
}
}
int main()
{
int max_c, n, t, m;
cin>>max_c>>n>>t>>m;
value[0] = 0;
rep(i,1,n+1)
cin>>value[i];
int x,y,z;
rep(i,0,m)
{
cin>>x>>y>>z;
G[x].pb((node){y,z});
G[y].pb((node){x,z});
}
int min_cost = INF;
dij(n,t,min_cost);
VI ans;
dfs(t,-1,-1);
int mmin1 = INF, pos1 = -1, tag = -1;
int mmin2 = INF, pos2 = -1;
rep(i,0,(int)paths.size())
{
int Sum = 0;
rep(j,0,(int)paths[i].size())
Sum += value[paths[i][j]];
int val = ((int)paths[i].size()-1) * max_c / 2 - Sum;
if (val >= 0 && mmin1 > val)
{
mmin1 = val;
pos1 = i;
tag = 1;
}
if (tag == -1 && val < 0 && mmin2 > -val)
{
mmin2 = -val;
pos2 = i;
}
}
int pos=-1, mmin=INF;
if (tag == 1)
{
pos = pos1;
mmin = mmin1;
}
if (tag == -1)
{
pos = pos2;
mmin = mmin2;
}
if (pos != -1)
{
int in = 0, out = 0;
if (tag == 1)
out = mmin;
else
in = mmin;
cout << out << ' ';
int sz = (int)paths[pos].size();
rep(i,0,sz-1)
cout << paths[pos][i] << "->";
cout << paths[pos][sz-1] <<" "<< in << endl;
}
return 0;
}
#include
using namespace std;
typedef pair P;
const int N = 1e5+10;
int n;
map mp;
vector node;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
string s,t;
cin>>s;
int x;
for(int i=0;i>t>>temp.first>>temp.second;
mp[t] = temp;
}
string p = s;
while(p!="-1"){
node.push_back(P(mp[p].first,p));
p = mp[p].second;
}
sort(node.begin(), node.end());
n = node.size();
if (n!=0){
cout<
1111 Online Map (30 point(s))
松弛条件修改dijstra
上面自行车那题一样, 但是我发现PAT出的题都是可以不用回溯pre数组, 而是直接把次要条件加入到松弛的判断中就行了,
但是需要注意的是, 如果cost的排序标准变成了两个条件cost[2], 那么priority_queue的关键词应该也要是两个cost[2]。
因为理论上, 等于是把dijstra的距离改成了两个参数综合的距离。
但是代码中我没用, 可能是没有这样的数据
#include
#define pb push_back
#define rep(i,l,r) for(int i=l;i P;
int n, m, s, t;
/*
对于A为主要条件, B为次要条件的题目, 可以把AB用一个cost[2]来存放
然后dijstra的算法中,松弛操作可以用一个better函数来判断是否松弛。
void dijstra(){
init que,vis,dis;
push(source), set source's parameter to zero;
while(!que.empty()):
if vis continue; vis = true
for all v in G[u]:
if !vis[v] && can_slack == true:
slack
push v to que
}
*/
/* global variant */
struct Node{
int v, cost[2];
Node(int _v, int _l, int _t){
v = _v;
cost[0] = _l;
cost[1] = _t;
}
Node(){};
};
vector G[N];
bool vis[N];
int dis[2][N], insec[N], pre[N];//dij parameter
int ans[2][N], top[2], mincost[2];//to store ans
/*function*/
bool better(int u, int v, Node &tp, int tag){
if (tag == 0)
return dis[0][v]==dis[0][u]+tp.cost[0]?dis[1][v] > dis[1][u]+tp.cost[1]:dis[0][v]>dis[0][u]+tp.cost[0];
else
return dis[1][v]==dis[1][u]+tp.cost[1]?insec[v] > insec[u]+1:dis[1][v]>dis[1][u]+tp.cost[1];
}
void dij(int tag){
priority_queue, greater
> que;
memset(dis, 0x3f, sizeof (dis));
memset(dis[1],0x3f,sizeof dis[1]);
memset(insec,0x3f,sizeof insec);
memset(vis, 0, sizeof vis);
memset(pre,-1, sizeof pre);
dis[0][s] = dis[1][s]= 0;
insec[s] = 1;
que.push(P(0,s));
while(!que.empty()){
P tp = que.top();que.pop();
int u = tp.second;
if (vis[u])continue;
vis[u] = true;
for(int i=0;i<(int)G[u].size();i++){
int v = G[u][i].v;
if (vis[v])continue;
if (better(u,v,G[u][i],tag)){ // just to adjust this condition functions
dis[0][v] = dis[0][u] + G[u][i].cost[0];
dis[1][v] = dis[1][u] + G[u][i].cost[1];
insec[v] = insec[u] + 1;
que.push(P(dis[tag][v], v));
pre[v] = u;
}
}
}
}
void out(int tag){
for(int i=top[tag]-1;i>0;i--){
cout< ";
}cout<>n>>m){
int x, y, tag, l, t;
top[0] = top[1] = 0;
for(int i=0;i>x>>y>>tag>>l>>t;
if (tag){
G[x].pb(Node(y, l, t));
}else{
G[x].pb(Node(y, l, t));
G[y].pb(Node(x, l, t));
}
}
cin>>s>>t;
for(int i=0;i<2;i++){
dij(i);
mincost[i] = dis[i][t];
int p = t;
while(p!=-1){
ans[i][top[i]++] = p;
p = pre[p];
}
}
bool fg = same_array(ans[0], ans[1], top[0], top[1]);
if (fg){
cout<<"Distance = "<