Fabric1.4:运行 first-network 网络
说明:运行 first-network 网络,必须先安装好 fabric1.4 的预置环境,fabric1.4 的安装可以参考此博文:https://www.cnblogs.com/zongmin/p/11635686.html。本文使用 fabric 版本为 v1.4.3,其它版本的 first-network 网络配置可能不同。
构建你的第一个网络(Build Your First network,BYFN)提供了一个 fabric 的示例网络。该示例网络中由两个组织构成,每个组织维护两个 peer 节点,默认使用 solo 共识服务。
1 脚本 byfn.sh
first-network 中有一个启动脚本 byfn.sh,利用构建的 Docker 镜像快速启动网络。该脚本会启动一个 orderer 节点和四个归属两个不同组织的 peer 节点,还将启动一个容器运行脚本,它将 peer 节点加入通道(Channel)、部署和实例化链码,并根据已部署的链码驱动交易执行。
以下是 byfn.sh 脚本的帮助文档:
$ ./byfn.sh
Usage:
byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-o <consensus-type>] [-i <imagetag>] [-a] [-n] [-v]
<mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'
- 'up' - bring up the network with docker-compose up
- 'down' - clear the network with docker-compose down
- 'restart' - restart the network
- 'generate' - generate required certificates and genesis block
- 'upgrade' - upgrade the network from version 1.3.x to 1.4.0
-c <channel name> - channel name to use (defaults to "mychannel")
-t <timeout> - CLI timeout duration in seconds (defaults to 10)
-d <delay> - delay duration in seconds (defaults to 3)
-f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)
-s <dbtype> - the database backend to use: goleveldb (default) or couchdb
-l <language> - the chaincode language: golang (default) or node
-o <consensus-type> - the consensus-type of the ordering service: solo (default), kafka, or etcdraft
-i <imagetag> - the tag to be used to launch the network (defaults to "latest")
-a - launch certificate authorities (no certificate authorities are launched by default)
-n - do not deploy chaincode (abstore chaincode is deployed by default)
-v - verbose mode
byfn.sh -h (print this message)
Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:
byfn.sh generate -c mychannel
byfn.sh up -c mychannel -s couchdb
byfn.sh up -c mychannel -s couchdb -i 1.4.0
byfn.sh up -l node
byfn.sh down -c mychannel
byfn.sh upgrade -c mychannel
Taking all defaults:
byfn.sh generate
byfn.sh up
byfn.sh down
-c:设置通道名称,默认为 mychannel,例:./byfn.sh up -c testchannel-t:设置 CLI 超时参数,不设置的情况下 CLI 将放弃 10 秒后发出查询请求的默认设置-l:设置智能合约的语言,默认是 go,例:./byfn.sh up -l java-o:设置排序服务方式,默认是 solo,例:./byfn.sh up -o kafka
2 生成证书
执行如下命令:
$ ./byfn.sh generate
运行该命令会为 fabric 网络的各种实体生成所需的证书与密钥,保存在 crypto-config 目录下。
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
/Users/xxx/dev/fabric-samples/bin/cryptogen
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
org1.example.com
2017-06-12 21:01:37.334 EDT [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.
...
/Users/xxx/dev/fabric-samples/bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
2017-06-12 21:01:37.558 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 002 intermediate certs folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts: no such file or directory]
...
2017-06-12 21:01:37.588 EDT [common/configtx/tool] doOutputBlock -> INFO 00b Generating genesis block
2017-06-12 21:01:37.590 EDT [common/configtx/tool] doOutputBlock -> INFO 00c Writing genesis block
#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
2017-06-12 21:01:37.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.644 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2017-06-12 21:01:37.645 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx
#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
2017-06-12 21:01:37.674 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.678 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2017-06-12 21:01:37.679 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
2017-06-12 21:01:37.700 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
3 启动网络
使用如下命令启动 fabric 网络:
$ ./byfn.sh up
注意:该命令会检查网络实体的证书是否生成,如果没有会先生成证书。因此,可以直接执行 ./byfn.sh up 命令,而无需执行 ./byfn.sh generate 命令。
执行日志如下:
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n]
proceeding ...
Creating network "net_byfn" with the default driver
Creating peer0.org1.example.com
Creating peer1.org1.example.com
Creating peer0.org2.example.com
Creating orderer.example.com
Creating peer1.org2.example.com
Creating cli
____ _____ _ ____ _____
/ ___| |_ _| / \ | _ \ |_ _|
\___ \ | | / _ \ | |_) | | |
___) | | | / ___ \ | _ < | |
|____/ |_| /_/ \_\ |_| \_\ |_|
Channel name : mychannel
Creating channel...
启动所有容器,然后驱动完整的应用程序场景。执行成功后,在终端会出现如下输出:
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query successful on peer1.org2 on channel 'mychannel' =====================
===================== All GOOD, BYFN execution completed =====================
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
屏幕后面发生了什么?
./byfn.sh up 启动完 orderer 节点、peer 节点和 CLI 容器之后,实际是调用 script.sh 脚本,该脚本是在 CLI 容器中执行,script.sh 脚本完成客户端交易执行操作。下面是 CLI 容器的定义,CLI 容器其实就是用户客户端,只不过是命令行客户端,运行在容器中。默认情况下,CLI 的身份是 admin.org1,连接 peer0.org1 节点,执行 script.sh 脚本。
cli:
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
- SYS_CHANNEL=$SYS_CHANNEL
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
#- FABRIC_LOGGING_SPEC=DEBUG
- FABRIC_LOGGING_SPEC=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
networks:
- byfn
下面简略描述 script.sh 的基本函数。
3.1 创建通道
createChannel() {
setGlobals 0 1 # admin.org1 连接 peer0.org1
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx >&log.txt
res=$?
set +x
else
set -x
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Channel creation failed"
echo "===================== Channel '$CHANNEL_NAME' created ===================== "
echo
}
admin.org1 连接 peer0.org1 节点,向 orderer 节点传递要创建的通道名称 $CHANNEL_NAME (默认为 mychannel)和通道配置交易 channel.tx。如果创建成功,则返回通道的创世区块 $CHANNEL_NANE.block,该区块包含 channel.tx 指定的通道配置信息,保存在 CLI 容器中。
3.2 加入通道
joinChannel () {
for org in 1 2; do
for peer in 0 1; do
joinChannelWithRetry $p$CHANNEL_NAMEeer $org
echo "===================== peer${peer}.org${org} joined channel '$CHANNEL_NAME' ===================== "
sleep $DELAY
echo
done
done
}
第一个 for 循环标识两个组织 org1 和 org2;第二个 for 循环标识两个组织 peer0 和 peer1。根据 $peer $org 先后顺序,四个节点分别是:
peer0.org1.example.compeer1.org1.example.compeer0.org2.example.compeer1.org2.example.com
这是 first-network 的默认网络结构,在 crypto-config.yaml 文件的 TwoOrgsChannel 部分定义,MSP 路径在 docker-compose-cli.yaml 文件中定义。
## Sometimes Join takes time hence RETRY at least 5 times
joinChannelWithRetry() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
set -x
peer channel join -b $CHANNEL_NAME.block >&log.txt
res=$?
set +x
cat log.txt
if [ $res -ne 0 -a $COUNTER -lt $MAX_RETRY ]; then
COUNTER=$(expr $COUNTER + 1)
echo "peer${PEER}.org${ORG} failed to join the channel, Retry after $DELAY seconds"
sleep $DELAY
joinChannelWithRetry $PEER $ORG
else
COUNTER=1
fi
verifyResult $res "After $MAX_RETRY attempts, peer${PEER}.org${ORG} has failed to join channel '$CHANNEL_NAME' "
}
在 joinChannelWithRetry 函数中的 setGlobals 是设置 CLI 容器的环境变量的函数。例如:setGlobals 1 2 设置 CLI 的身份为 admin.org2,连接 peer1.org2 节点。
使用 peer channel join 命令让节点加入通道,$CHANNEL_NAME.block 就是前面创建通道成功时返回的区块,该区块在上面 peer0.org1 创建通道时保持在 CLI 容器内,所以能直接使用。节点成功加入通道后会创建 CHANNEL_NAME.block 开头的链。
3.3 更新锚节点
一个组织只能有一个锚节点,节点加入通道后才能进行更新。
updateAnchorPeers() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx >&log.txt
res=$?
set +x
else
set -x
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Anchor peer update failed"
echo "===================== Anchor peers updated for org '$CORE_PEER_LOCALMSPID' on channel '$CHANNEL_NAME' ===================== "
sleep $DELAY
echo
}
更新 org1 的锚节点 peer0.org1.example.com 和 org2 的锚节点 peer0.org2.example.com 。过程是将 Org1MSPanchors.tx 和 Org2MSPanchors.tx 交易连同通道名称 $CHANNEL_NAME 传递给 orderer。
3.4 安装链码
installChaincode() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
VERSION=${3:-1.0}
set -x
peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt
res=$?
set +x
cat log.txt
verifyResult $res "Chaincode installation on peer${PEER}.org${ORG} has failed"
echo "===================== Chaincode is installed on peer${PEER}.org${ORG} ===================== "
echo
}
安装链码需要指定链码的配置信息,-n 是链码的名称;-v 是版本号;-l 是指定链码的语言,如果不使用该标志默认使用 go 语言;-p 是指向链码路径,默认是 github.com/chaincode/chaincode_example02/go/。
3.5 实例化链码
instantiateChaincode() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
VERSION=${3:-1.0}
# while 'peer chaincode' command can get the orderer endpoint from the peer
# (if join was successful), let's supply it directly as we know it using
# the "-o" option
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v ${VERSION} -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt
res=$?
set +x
else
set -x
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Chaincode instantiation on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' failed"
echo "===================== Chaincode is instantiated on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== "
echo
}
fabric 网络上的链码是多次安装,一次实例化,该函数只需运行一遍即可。
链码在通道 $CHANNEL_NAME 上实例化。实例化将链码添加到通道上,启动目标节点的容器,初始化与链码相关的初始值,这里的初始值为 ["a","100","b","200"]。”实例化“ 过程会产生链码的容器,例如: dev-peer0-org1.example.com-mycc-1.0 。实例化过程需要指定背书策略,通过 -P 参数设置,这里的策略定义为 AND ('Org1MSP.peer','Org2MSP.peer') ,表示任何交易必须要有 org1 和 org2 节点的共同背书。此处背书的节点只能是以下四对组合:
peer0.org1.example.com和peer0.org2.example.compeer0.org1.example.com和peer1.org2.example.compeer1.org1.example.com和peer0.org2.example.compeer1.org1.example.com和peer1.org2.example.com
3.6 调用链码
# chaincodeInvoke <peer> <org> ...
# Accepts as many peer/org pairs as desired and requests endorsement from each
chaincodeInvoke() {
parsePeerConnectionParameters $@
res=$?
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
# while 'peer chaincode' command can get the orderer endpoint from the
# peer (if join was successful), let's supply it directly as we know
# it using the "-o" option
if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
set -x
peer chaincode invoke -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt
res=$?
set +x
else
set -x
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt
res=$?
set +x
fi
cat log.txt
verifyResult $res "Invoke execution on $PEERS failed "
echo "===================== Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME' ===================== "
echo
}
向 $PEER_CONN_PARM 发送一个调用,以实现从 a 中转移 10 给 b。$PEER_CONN_PARM 就是上面四对组合中的任意一对背书节点。在调用链码的过程中,如果某个节点的链码容器还没有启动,就会执行启动。
3.7 查询链码
chaincodeQuery() {
PEER=$1
ORG=$2
setGlobals $PEER $ORG
EXPECTED_RESULT=$3
echo "===================== Querying on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME'... ===================== "
local rc=1
local starttime=$(date +%s)
# continue to poll
# we either get a successful response, or reach TIMEOUT
while
test "$(($(date +%s) - starttime))" -lt "$TIMEOUT" -a $rc -ne 0
do
sleep $DELAY
echo "Attempting to Query peer${PEER}.org${ORG} ...$(($(date +%s) - starttime)) secs"
set -x
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' >&log.txt
res=$?
set +x
test $res -eq 0 && VALUE=$(cat log.txt | awk '/Query Result/ {print $NF}')
test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
# removed the string "Query Result" from peer chaincode query command
# result. as a result, have to support both options until the change
# is merged.
test $rc -ne 0 && VALUE=$(cat log.txt | egrep '^[0-9]+$')
test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
done
echo
cat log.txt
if test $rc -eq 0; then
echo "===================== Query successful on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== "
else
echo "!!!!!!!!!!!!!!! Query result on peer${PEER}.org${ORG} is INVALID !!!!!!!!!!!!!!!!"
echo "================== ERROR !!! FAILED to execute End-2-End Scenario =================="
echo
exit 1
fi
}
向装有链码的节点发送一个查询查看 a 的值。如果返回值为 90,则表明在之前的交易中 “a” 的值被减去 10。
这证明了什么?
为了能成功地对账本进行读/写操作,链码必须按照在相应的节点上。只有在链码中执行初始化(Init函数)、调用(Invoke函数)交易(读/写),或者查询 “a” 的值,才会为节点启动一个链码容器(交易引起容器的启动)。另外,通道中的所有节点都维护账本的一个精确副本,该副本包括在区块中存储不可变、按顺序排列的记录的区块链,以及用户维护当前账本的状态数据库。
4 关闭网络
执行下面命令:
$ ./byfn.sh down
Stopping for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
WARNING: The BYFN_CA2_PRIVATE_KEY variable is not set. Defaulting to a blank string.
WARNING: The BYFN_CA1_PRIVATE_KEY variable is not set. Defaulting to a blank string.
Stopping cli ... done
Stopping peer1.org1.example.com ... done
Stopping peer1.org2.example.com ... done
Stopping peer0.org1.example.com ... done
Stopping peer0.org2.example.com ... done
Stopping orderer.example.com ... done
Removing cli ... done
Removing peer1.org1.example.com ... done
Removing peer1.org2.example.com ... done
Removing peer0.org1.example.com ... done
Removing peer0.org2.example.com ... done
Removing orderer.example.com ... done
Removing network net_byfn
Removing volume net_peer0.org3.example.com
WARNING: Volume net_peer0.org3.example.com not found.
Removing volume net_peer1.org3.example.com
WARNING: Volume net_peer1.org3.example.com not found.
Removing volume net_orderer2.example.com
WARNING: Volume net_orderer2.example.com not found.
Removing volume net_orderer.example.com
Removing volume net_peer0.org2.example.com
Removing volume net_peer0.org1.example.com
Removing volume net_peer1.org1.example.com
Removing volume net_peer1.org2.example.com
Removing volume net_orderer5.example.com
WARNING: Volume net_orderer5.example.com not found.
Removing volume net_orderer4.example.com
WARNING: Volume net_orderer4.example.com not found.
Removing volume net_orderer3.example.com
WARNING: Volume net_orderer3.example.com not found.
该命令将关闭网络,删除证书材料和组件,并从 Docker 注册表中删除链码镜像。crypto-config 文件夹会被删除,channel-artifacts 文件夹下的 channel.tx、genesis.block、Org1MSPanchors.tx 和 Org2MSPanchors.tx 这四个文件会被删除。
参考
《Hyperledger Fabric 核心技术》
Fabric1.4:运行 first-network 网络的更多相关文章
- core java 10~12(多线程 & I/O & Network网络编程)
MODULE 10 Threads 多线程-------------------------------- 进程: 计算机在运行过程中的任务单元,CPU在一个时间点上只能执行一个进程,但在一个时间段上 ...
- 【BZOJ】【1834】【ZJOI2010】Network 网络扩容
网络流/费用流 这题……我一开始sb了. 第一问简单的最大流…… 第二问是要建费用流的图的……但是是在第一问的最大流跑完以后的残量网络上建,而不是重建…… 我们令残量网络上原有的弧的费用全部为0(因为 ...
- bzoj1834: [ZJOI2010]network 网络扩容
努力看了很久样例一直过不了...然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了...然后突然想到啊原来的边可以用啊为什么不用...于是A了...感人肺腑 #include<cstdio> ...
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然 后跑最小费用最大流就OK了. ---- ...
- ZOJ 1542 POJ 1861 Network 网络 最小生成树,求最长边,Kruskal算法
题目连接:problemId=542" target="_blank">ZOJ 1542 POJ 1861 Network 网络 Network Time Limi ...
- BZOJ_1834_[ZJOI2010]network 网络扩容_费用流
BZOJ_1834_[ZJOI2010]network 网络扩容_费用流 题意: 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的 ...
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
[BZOJ1834][ZJOI2010]network 网络扩容 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不 ...
- bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一 ...
- BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 3394 Solved: 1774 [Subm ...
- 【bzoj1834】[ZJOI2010]network 网络扩容
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 2701 Solved: 1368[Submit ...
随机推荐
- Android 设置TextView字体颜色
设置TextView字体的颜色其实很简单,尤其是直接在XML文件中,可以直接通过textColor属性指定颜色值,达到设置文本颜色的效果:那在代码中如何动态设置字体的颜色值呢? 接下来,介绍如何通过J ...
- NIO 中文乱码自我解决的简单DEMO
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...
- Python--day62--删除出版社
删除成出版社关键代码:
- Python--day47--mysql慢日志记录
- Pytorch的LSTM的理解
class torch.nn.LSTM(*args, **kwargs) 参数列表 input_size:x的特征维度 hidden_size:隐藏层的特征维度 num_layers:lstm隐层的层 ...
- Scrap简介
原文:https://blog.csdn.net/ssw_1990/article/details/51254227 提到Python与网络爬虫,可能会想到urllib,urllib2,Beautif ...
- Educational Codeforces Round 65 (Rated for Div. 2) E. Range Deleting(思维+coding)
传送门 参考资料: [1]:https://blog.csdn.net/weixin_43262291/article/details/90271693 题意: 给你一个包含 n 个数的序列 a,并且 ...
- Spring Cloud探路(一) Erueka服务器的建立
组件名:Netflix Eureka 作用:支撑微服务的自注册.自发现,提供负载均衡能力 开发环境使用IDEA 1.新建Eureka Server,新建maven项目,配置pom.xml <p ...
- P1098 方程解的个数
题目描述 给出一个正整数N,请你求出x+y+z=N这个方程的正整数解的组数(1<=x<=y<=z<1000).其中,1<=x<=y<=z<=N . 输入 ...
- 【p083】传球游戏
Time Limit: 1 second Memory Limit: 50 MB [问题描述] 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样 ...